merge conflict with db/manifest resolved
This commit is contained in:
commit
94421c03c0
|
|
@ -1,7 +1,7 @@
|
|||
source 'http://rubygems.org'
|
||||
|
||||
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
|
||||
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
|
||||
devenv = ENV["BUILD_NUMBER"].nil?
|
||||
|
||||
if devenv
|
||||
gem 'jam_db', :path=> "../db/target/ruby_package"
|
||||
|
|
|
|||
|
|
@ -156,4 +156,5 @@ scheduled_sessions.sql
|
|||
add_last_jam_user_fields.sql
|
||||
remove_lat_lng_user_fields.sql
|
||||
update_get_work_for_larger_radius.sql
|
||||
periodic_emails.sql
|
||||
remember_extra_scoring_data.sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
ALTER TABLE email_batches ADD COLUMN type VARCHAR(64) NOT NULL DEFAULT 'JamRuby::EmailBatch';
|
||||
ALTER TABLE email_batches ADD COLUMN sub_type VARCHAR(64);
|
||||
|
||||
ALTER TABLE email_batches ALTER COLUMN body DROP NOT NULL;
|
||||
ALTER TABLE email_batches ALTER COLUMN subject DROP NOT NULL;
|
||||
|
||||
ALTER TABLE email_batch_sets ADD COLUMN trigger_index INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE email_batch_sets ADD COLUMN sub_type VARCHAR(64);
|
||||
ALTER TABLE email_batch_sets ADD COLUMN user_id VARCHAR(64);
|
||||
|
||||
CREATE INDEX email_batch_sets_progress_idx ON email_batch_sets(user_id, sub_type);
|
||||
CREATE INDEX users_musician_email_idx ON users(subscribe_email, musician);
|
||||
|
||||
UPDATE users set first_social_promoted_at = first_liked_us;
|
||||
ALTER TABLE users DROP column first_liked_us;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
--color
|
||||
--format progress
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem "rspec"
|
||||
gem "capybara"
|
||||
gem "capybara-screenshot"
|
||||
gem "poltergeist"
|
||||
gem "launchy" # used for opening pages/screenshots when debugging
|
||||
|
||||
# these used only for the Fixnum#seconds method :-/
|
||||
gem "i18n"
|
||||
gem "activesupport"
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (3.1.12)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.3.6)
|
||||
capybara (2.2.1)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
capybara-screenshot (0.3.19)
|
||||
capybara (>= 1.0, < 3)
|
||||
launchy
|
||||
cliver (0.3.2)
|
||||
diff-lcs (1.2.5)
|
||||
i18n (0.6.9)
|
||||
launchy (2.4.2)
|
||||
addressable (~> 2.3)
|
||||
mime-types (2.2)
|
||||
mini_portile (0.5.3)
|
||||
multi_json (1.10.0)
|
||||
nokogiri (1.6.1)
|
||||
mini_portile (~> 0.5.0)
|
||||
nokogiri (1.6.1-x86-mingw32)
|
||||
mini_portile (~> 0.5.0)
|
||||
poltergeist (1.5.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
multi_json (~> 1.0)
|
||||
websocket-driver (>= 0.2.0)
|
||||
rack (1.5.2)
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rspec (2.14.1)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-core (2.14.8)
|
||||
rspec-expectations (2.14.5)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.14.6)
|
||||
websocket-driver (0.3.3)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86-mingw32
|
||||
|
||||
DEPENDENCIES
|
||||
activesupport
|
||||
capybara
|
||||
capybara-screenshot
|
||||
i18n
|
||||
launchy
|
||||
poltergeist
|
||||
rspec
|
||||
15
web/spec/features/production_spec.rb → monitor/spec/production_spec.rb
Normal file → Executable file
15
web/spec/features/production_spec.rb → monitor/spec/production_spec.rb
Normal file → Executable file
|
|
@ -1,9 +1,14 @@
|
|||
require 'spec_helper'
|
||||
|
||||
# these tests MUST be idempotent and DO use actual production user accounts on www
|
||||
www = 'http://www.jamkazam.com'
|
||||
# these tests should be idempotent, and not spammy to other JK users
|
||||
# because they DO use actual production user accounts on www (see the TestUsers below)
|
||||
|
||||
describe "Production site at #{www}", :test_www => true, :js => true, :type => :feature, :capybara_feature => true do
|
||||
# Jenkins executes rspec on this folder every 15 minutes or so.
|
||||
# SO don't use this to test something like a public session unless you want all the world to see
|
||||
|
||||
www = ENV['MONITOR_URL'] || 'http://www.jamkazam.com'
|
||||
|
||||
describe "Deployed site at #{www}", :js => true, :type => :feature, :capybara_feature => true do
|
||||
|
||||
subject { page }
|
||||
|
||||
|
|
@ -28,7 +33,6 @@ describe "Production site at #{www}", :test_www => true, :js => true, :type =>
|
|||
first_name + ' ' + last_name
|
||||
end
|
||||
end
|
||||
|
||||
user1 = TestUser.new({ email: 'anthony+jim@jamkazam.com', password: 'j4m!t3st3r', first_name: 'Jim', last_name: 'Smith', id: '68e8eea2-140d-44c1-b711-10d07ce70f96' })
|
||||
user2 = TestUser.new({ email: 'anthony+john@jamkazam.com', password: 'j4m!t3st3r', first_name: 'John', last_name: 'Jones', id: '5bbcf689-2f73-452d-815a-c4f44e9e7f3e' })
|
||||
|
||||
|
|
@ -46,7 +50,7 @@ describe "Production site at #{www}", :test_www => true, :js => true, :type =>
|
|||
end
|
||||
|
||||
it "is possible for #{user1} and #{user2} to see each other online, and to send messages" do
|
||||
# this example heavily based on text_message_spec.rb
|
||||
# this example heavily based on text_message_spec.rb in 'web'
|
||||
|
||||
in_client(user1) do
|
||||
sign_in_poltergeist(user1)
|
||||
|
|
@ -89,4 +93,3 @@ describe "Production site at #{www}", :test_www => true, :js => true, :type =>
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
require 'rubygems'
|
||||
require 'active_support/time'
|
||||
require 'capybara'
|
||||
require 'capybara/rspec'
|
||||
require 'capybara-screenshot'
|
||||
require 'capybara-screenshot/rspec'
|
||||
require 'capybara/poltergeist'
|
||||
|
||||
require 'support/client_interactions' #TODO: Strip out the helper methods that production_spec does not use
|
||||
require 'support/utilities'
|
||||
require 'support/stubs' # to make the JamXXXX warnings go away
|
||||
|
||||
# This file was generated by the `rspec --init` command. Conventionally, all
|
||||
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
||||
# Require this file using `require "spec_helper"` to ensure that it is only
|
||||
# loaded once.
|
||||
#
|
||||
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
||||
RSpec.configure do |config|
|
||||
config.treat_symbols_as_metadata_keys_with_true_values = true
|
||||
config.run_all_when_everything_filtered = true
|
||||
config.filter_run :focus
|
||||
|
||||
# Run specs in random order to surface order dependencies. If you find an
|
||||
# order dependency and want to debug it, you can fix the order by providing
|
||||
# the seed, which is printed after each run.
|
||||
# --seed 1234
|
||||
config.order = 'random'
|
||||
|
||||
config.include Capybara::DSL
|
||||
end
|
||||
|
||||
Capybara.javascript_driver = :poltergeist
|
||||
Capybara.default_driver = :poltergeist
|
||||
Capybara.run_server = false # since we're testing an app outside this project
|
||||
Capybara.default_wait_time = 15 # ^^ ditto
|
||||
|
||||
Capybara.configure do |config|
|
||||
config.match = :one
|
||||
config.exact_options = true
|
||||
config.ignore_hidden_elements = true
|
||||
config.visible_text_only = true
|
||||
end
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
|
||||
# methods here all assume you are in /client
|
||||
|
||||
NOTIFICATION_PANEL = '[layout-id="panelNotifications"]'
|
||||
|
||||
# enters text into the search sidebar
|
||||
def site_search(text, options = {})
|
||||
within('#searchForm') do
|
||||
fill_in "search-input", with: text
|
||||
end
|
||||
|
||||
if options[:expand]
|
||||
page.driver.execute_script("jQuery('#searchForm').submit()")
|
||||
find('h1', text:'search results')
|
||||
end
|
||||
end
|
||||
|
||||
# goes to the musician tile, and tries to find a musician
|
||||
def find_musician(user)
|
||||
visit "/client#/musicians"
|
||||
|
||||
timeout = 30
|
||||
|
||||
start = Time.now
|
||||
# scroll by 100px until we find a user with the right id
|
||||
while page.all('#end-of-musician-list').length == 0
|
||||
page.execute_script('jQuery("#musician-filter-results").scrollTo("+=100px", 0, {axis:"y"})')
|
||||
found = page.all(".result-list-button-wrapper[data-musician-id='#{user.id}']")
|
||||
if found.length == 1
|
||||
return found[0]
|
||||
elsif found.length > 1
|
||||
raise "ambiguous results in musician list"
|
||||
end
|
||||
|
||||
if Time.now - start > timeout
|
||||
raise "unable to find musician #{user} within #{timeout} seconds"
|
||||
end
|
||||
end
|
||||
|
||||
raise "unable to find musician #{user}"
|
||||
end
|
||||
|
||||
def initiate_text_dialog(user)
|
||||
|
||||
# verify that the chat window is grayed out
|
||||
site_search(user.first_name, expand: true)
|
||||
|
||||
find("#search-results a[user-id=\"#{user.id}\"][hoveraction=\"musician\"]", text: user.name).hover_intent
|
||||
find('#musician-hover #btnMessage').trigger(:click)
|
||||
find('h1', text: 'conversation with ' + user.name)
|
||||
end
|
||||
|
||||
# sends a text message in the chat interface.
|
||||
def send_text_message(msg, options={})
|
||||
find('#text-message-dialog') # assert that the dialog is showing already
|
||||
|
||||
within('#text-message-dialog form.text-message-box') do
|
||||
fill_in 'new-text-message', with: msg
|
||||
end
|
||||
find('#text-message-dialog .btn-send-text-message').trigger(:click)
|
||||
find('#text-message-dialog .previous-message-text', text: msg) unless options[:should_fail]
|
||||
|
||||
# close the dialog if caller specified close_on_send
|
||||
if options[:close_on_send]
|
||||
find('#text-message-dialog .btn-close-dialog', text: 'CLOSE').trigger(:click) if options[:close_on_send]
|
||||
page.should have_no_selector('#text-message-dialog')
|
||||
end
|
||||
|
||||
if options[:should_fail]
|
||||
find('#notification').should have_text(options[:should_fail])
|
||||
end
|
||||
end
|
||||
|
||||
# sends a chat message during session
|
||||
def send_chat_message(msg)
|
||||
find("[layout-id=\"panelChat\"] .chat-sender").should be_visible
|
||||
|
||||
within("[layout-id=\"panelChat\"] .chat-sender form.chat-message-form") do
|
||||
fill_in 'new-chat-message', with: msg
|
||||
end
|
||||
find("[layout-id=\"panelChat\"] .chat-sender .btn-send-chat-message").trigger(:click)
|
||||
end
|
||||
|
||||
def open_notifications
|
||||
find("#{NOTIFICATION_PANEL} .panel-header").trigger(:click)
|
||||
end
|
||||
|
||||
|
||||
def hover_intent(element)
|
||||
element.hover
|
||||
element.hover
|
||||
end
|
||||
|
||||
# forces document.hasFocus() to return false
|
||||
def document_blur
|
||||
page.evaluate_script(%{(function() {
|
||||
// save original
|
||||
if(!window.documentFocus) { window.documentFocus = window.document.hasFocus; }
|
||||
|
||||
window.document.hasFocus = function() {
|
||||
console.log("document.hasFocus() returns false");
|
||||
return false;
|
||||
}
|
||||
})()})
|
||||
end
|
||||
|
||||
def document_focus
|
||||
page.evaluate_script(%{(function() {
|
||||
// save original
|
||||
if(!window.documentFocus) { window.documentFocus = window.document.hasFocus; }
|
||||
|
||||
window.document.hasFocus = function() {
|
||||
console.log("document.hasFocus() returns true");
|
||||
return true;
|
||||
}
|
||||
})()})
|
||||
end
|
||||
|
||||
# simulates focus event on window
|
||||
def window_focus
|
||||
page.evaluate_script(%{window.jQuery(window).trigger('focus');})
|
||||
end
|
||||
|
||||
def close_websocket
|
||||
page.evaluate_script("window.JK.JamServer.close(true)")
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
module JamRuby
|
||||
class User
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def signin_path
|
||||
'/signin'
|
||||
end
|
||||
|
|
@ -0,0 +1,481 @@
|
|||
|
||||
# add a hover_intent method to element, so that you can do find(selector).hover_intent
|
||||
module Capybara
|
||||
module Node
|
||||
class Element
|
||||
|
||||
def attempt_hover
|
||||
begin
|
||||
hover
|
||||
rescue => e
|
||||
end
|
||||
end
|
||||
def hover_intent
|
||||
hover
|
||||
sleep 0.3
|
||||
attempt_hover
|
||||
sleep 0.3
|
||||
attempt_hover
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# holds a single test's session name's, mapped to pooled session names
|
||||
$capybara_session_mapper = {}
|
||||
|
||||
# called in before (or after) test, to make sure each test run has it's own map of session names
|
||||
def reset_session_mapper
|
||||
$capybara_session_mapper.clear
|
||||
|
||||
Capybara.session_name = :default
|
||||
end
|
||||
|
||||
# manages the mapped session name
|
||||
def mapped_session_name(session_name)
|
||||
return :default if session_name == :default # special treatment for the built-in session
|
||||
$capybara_session_mapper[session_name] ||= 'session_' + $capybara_session_mapper.length.to_s
|
||||
end
|
||||
|
||||
# in place of ever using Capybara.session_name directly,
|
||||
# this utility is used to handle the mapping of session names in a way across all tests runs
|
||||
def in_client(name)
|
||||
session_name = name.class == JamRuby::User ? name.id : name
|
||||
|
||||
Capybara.session_name = mapped_session_name(session_name)
|
||||
|
||||
yield
|
||||
end
|
||||
|
||||
|
||||
def cookie_jar
|
||||
Capybara.current_session.driver.browser.current_session.instance_variable_get(:@rack_mock_session).cookie_jar
|
||||
end
|
||||
|
||||
|
||||
#see also ruby/spec/support/utilities.rb
|
||||
JAMKAZAM_TESTING_BUCKET = 'jamkazam-testing' #at least, this is the name given in jam-ruby
|
||||
def wipe_s3_test_bucket
|
||||
s3 = AWS::S3.new(:access_key_id => Rails.application.config.aws_access_key_id,
|
||||
:secret_access_key => Rails.application.config.aws_secret_access_key)
|
||||
test_bucket = s3.buckets[JAMKAZAM_TESTING_BUCKET]
|
||||
if test_bucket.name == JAMKAZAM_TESTING_BUCKET
|
||||
test_bucket.objects.each do |obj|
|
||||
obj.delete
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def sign_in(user)
|
||||
visit signin_path
|
||||
fill_in "Email", with: user.email
|
||||
fill_in "Password", with: user.password
|
||||
click_button "SIGN IN"
|
||||
# Sign in when not using Capybara as well.
|
||||
cookie_jar[:remember_token] = user.remember_token
|
||||
end
|
||||
|
||||
def set_cookie(k, v)
|
||||
case Capybara.current_session.driver
|
||||
when Capybara::Poltergeist::Driver
|
||||
page.driver.set_cookie(k,v)
|
||||
when Capybara::RackTest::Driver
|
||||
headers = {}
|
||||
Rack::Utils.set_cookie_header!(headers,k,v)
|
||||
cookie_string = headers['Set-Cookie']
|
||||
Capybara.current_session.driver.browser.set_cookie(cookie_string)
|
||||
when Capybara::Selenium::Driver
|
||||
page.driver.browser.manage.add_cookie(:name=>k, :value=>v)
|
||||
else
|
||||
raise "no cookie-setter implemented for driver #{Capybara.current_session.driver.class.name}"
|
||||
end
|
||||
end
|
||||
|
||||
def sign_in_poltergeist(user, options = {})
|
||||
validate = options[:validate]
|
||||
validate = true if validate.nil?
|
||||
|
||||
visit signin_path
|
||||
fill_in "Email Address:", with: user.email
|
||||
fill_in "Password:", with: user.password
|
||||
click_button "SIGN IN"
|
||||
|
||||
wait_until_curtain_gone
|
||||
|
||||
# presence of this means websocket gateway is not working
|
||||
page.should have_no_selector('.no-websocket-connection') if validate
|
||||
end
|
||||
|
||||
|
||||
def sign_out()
|
||||
if Capybara.javascript_driver == :poltergeist
|
||||
page.driver.remove_cookie(:remember_token)
|
||||
else
|
||||
page.driver.browser.manage.remove_cookie :name => :remember_token
|
||||
end
|
||||
end
|
||||
|
||||
def sign_out_poltergeist(options = {})
|
||||
find('.userinfo').hover()
|
||||
click_link 'Sign Out'
|
||||
should_be_at_root if options[:validate]
|
||||
end
|
||||
|
||||
def should_be_at_root
|
||||
find('h1', text: 'Play music together over the Internet as if in the same room')
|
||||
end
|
||||
|
||||
def leave_music_session_sleep_delay
|
||||
# add a buffer to ensure WSG has enough time to expire
|
||||
sleep_dur = (Rails.application.config.websocket_gateway_connect_time_stale_browser +
|
||||
Rails.application.config.websocket_gateway_connect_time_expire_browser) * 1.4
|
||||
sleep sleep_dur
|
||||
end
|
||||
|
||||
|
||||
def wait_for_ajax(wait=Capybara.default_wait_time)
|
||||
wait = wait * 10 #(because we sleep .1)
|
||||
|
||||
counter = 0
|
||||
while page.execute_script("$.active").to_i > 0
|
||||
counter += 1
|
||||
sleep(0.1)
|
||||
raise "AJAX request took longer than #{wait} seconds." if counter >= wait
|
||||
end
|
||||
end
|
||||
|
||||
# waits until the user object has been requested, which comes after the 'curtain' is lifted
|
||||
# and after a call to /api/user/:id for the current user is called initially
|
||||
def wait_until_user(wait=Capybara.default_wait_time)
|
||||
wait = wait * 10 #(because we sleep .1)
|
||||
|
||||
counter = 0
|
||||
# while page.execute_script("$('.curtain').is(:visible)") == "true"
|
||||
# counter += 1
|
||||
# sleep(0.1)
|
||||
# raise "Waiting for user to populate took longer than #{wait} seconds." if counter >= wait
|
||||
# end
|
||||
end
|
||||
|
||||
def wait_until_curtain_gone
|
||||
page.should have_no_selector('.curtain')
|
||||
end
|
||||
|
||||
def wait_to_see_my_track
|
||||
within('div.session-mytracks') {first('div.session-track.track')}
|
||||
end
|
||||
|
||||
def repeat_for(duration=Capybara.default_wait_time)
|
||||
finish_time = Time.now + duration.seconds
|
||||
loop do
|
||||
yield
|
||||
sleep 1 # by default this will execute the block every 1 second
|
||||
break if (Time.now > finish_time)
|
||||
end
|
||||
end
|
||||
|
||||
def determine_test_name(metadata, test_name_buffer = '')
|
||||
description = metadata[:description_args]
|
||||
if description.kind_of?(Array)
|
||||
description = description[0]
|
||||
end
|
||||
if metadata.has_key? :example_group
|
||||
return determine_test_name(metadata[:example_group], "#{description} #{test_name_buffer}")
|
||||
else
|
||||
return "#{description} #{test_name_buffer}"
|
||||
end
|
||||
end
|
||||
|
||||
def get_description
|
||||
description = example.metadata[:description_args]
|
||||
if description.kind_of?(Array)
|
||||
description = description[0]
|
||||
end
|
||||
return description
|
||||
end
|
||||
|
||||
# will select the value from a easydropdown'ed select element
|
||||
def jk_select(text, select)
|
||||
|
||||
# the approach here is to find the hidden select element, and work way back up to the elements that need to be interacted with
|
||||
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]').trigger(:click)
|
||||
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown-wrapper") and contains(@class, "easydropdown-wrapper") and contains(@class, "open")]').find('li', text: text).trigger(:click)
|
||||
|
||||
# works, but is 'cheating' because of visible = false
|
||||
#select(genre, :from => 'genres', :visible => false)
|
||||
end
|
||||
|
||||
# takes, or creates, a unique session description which is returned for subsequent calls to join_session to use
|
||||
# in finding this session)
|
||||
def create_session(options={})
|
||||
creator = options[:creator] || FactoryGirl.create(:user)
|
||||
unique_session_desc = options[:description] || "create_join_session #{SecureRandom.urlsafe_base64}"
|
||||
genre = options[:genre] || 'Rock'
|
||||
musician_access = options[:musician_access].nil? ? true : options[:musician_access]
|
||||
fan_access = options[:fan_access].nil? ? true : options[:fan_access]
|
||||
|
||||
# create session in one client
|
||||
in_client(creator) do
|
||||
page.driver.resize(1500, 800) # makes sure all the elements are visible
|
||||
emulate_client
|
||||
sign_in_poltergeist creator
|
||||
wait_until_curtain_gone
|
||||
visit "/client#/createSession"
|
||||
expect(page).to have_selector('h2', text: 'session info')
|
||||
|
||||
within('#create-session-form') do
|
||||
fill_in('description', :with => unique_session_desc)
|
||||
#select(genre, :from => 'genres', :visible => false) # this works, but is 'cheating' because easydropdown hides the native select element
|
||||
jk_select(genre, '#create-session-form select[name="genres"]')
|
||||
|
||||
jk_select(musician_access ? 'Public' : 'Private', '#create-session-form select#musician-access')
|
||||
jk_select(fan_access ? 'Public' : 'Private', '#create-session-form select#fan-access')
|
||||
find('#create-session-form div.musician-access-false.iradio_minimal').trigger(:click)
|
||||
find('div.intellectual-property ins').trigger(:click)
|
||||
find('#btn-create-session').trigger(:click) # fails if page width is low
|
||||
end
|
||||
|
||||
# verify that the in-session page is showing
|
||||
expect(page).to have_selector('h2', text: 'my tracks')
|
||||
find('#session-screen .session-mytracks .session-track')
|
||||
end
|
||||
|
||||
return creator, unique_session_desc, genre
|
||||
|
||||
end
|
||||
|
||||
# this code assumes that there are no music sessions in the database. it should fail on the
|
||||
# find('.join-link') call if > 1 session exists because capybara will complain of multiple matches
|
||||
def join_session(joiner, options)
|
||||
description = options[:description]
|
||||
|
||||
in_client(joiner) do
|
||||
page.driver.resize(1500, 800) # makes sure all the elements are visible
|
||||
emulate_client
|
||||
sign_in_poltergeist joiner
|
||||
wait_until_curtain_gone
|
||||
visit "/client#/findSession"
|
||||
|
||||
# verify the session description is seen by second client
|
||||
expect(page).to have_text(description)
|
||||
find('.join-link').trigger(:click)
|
||||
find('#btn-accept-terms').trigger(:click)
|
||||
expect(page).to have_selector('h2', text: 'my tracks')
|
||||
find('#session-screen .session-mytracks .session-track')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
def emulate_client
|
||||
page.driver.headers = { 'User-Agent' => ' JamKazam ' }
|
||||
end
|
||||
|
||||
def create_join_session(creator, joiners=[], options={})
|
||||
options[:creator] = creator
|
||||
creator, unique_session_desc = create_session(options)
|
||||
|
||||
# find session in second client
|
||||
joiners.each do |joiner|
|
||||
join_session(joiner, description: unique_session_desc)
|
||||
end
|
||||
|
||||
return creator, unique_session_desc
|
||||
end
|
||||
|
||||
def formal_leave_by user
|
||||
in_client(user) do
|
||||
find('#session-leave').trigger(:click)
|
||||
#find('#btn-accept-leave-session').trigger(:click)
|
||||
expect(page).to have_selector('h2', text: 'feed')
|
||||
end
|
||||
end
|
||||
|
||||
def start_recording_with(creator, joiners=[], genre=nil)
|
||||
create_join_session(creator, joiners, {genre: genre})
|
||||
in_client(creator) do
|
||||
find('#recording-start-stop').trigger(:click)
|
||||
find('#recording-status').should have_content 'Stop Recording'
|
||||
end
|
||||
joiners.each do |joiner|
|
||||
in_client(joiner) do
|
||||
find('#notification').should have_content 'started a recording'
|
||||
find('#recording-status').should have_content 'Stop Recording'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def stop_recording
|
||||
find('#recording-start-stop').trigger(:click)
|
||||
end
|
||||
|
||||
def assert_recording_finished
|
||||
find('#recording-status').should have_content 'Make a Recording'
|
||||
should have_selector('h1', text: 'recording finished')
|
||||
end
|
||||
|
||||
def check_recording_finished_for(users=[])
|
||||
users.each do |user|
|
||||
in_client(user) do
|
||||
assert_recording_finished
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def claim_recording(name, description)
|
||||
find('#recording-finished-dialog h1')
|
||||
fill_in "claim-recording-name", with: name
|
||||
fill_in "claim-recording-description", with: description
|
||||
find('#keep-session-recording').trigger(:click)
|
||||
page.should have_no_selector('h1', text: 'recording finished')
|
||||
end
|
||||
|
||||
def set_session_as_private()
|
||||
find('#session-settings-button').trigger(:click)
|
||||
within('#session-settings-dialog') do
|
||||
jk_select("Private", '#session-settings-dialog #session-settings-musician-access')
|
||||
#select('Private', :from => 'session-settings-musician-access')
|
||||
find('#session-settings-dialog-submit').trigger(:click)
|
||||
end
|
||||
# verify it's dismissed
|
||||
page.should have_no_selector('h1', text: 'update session settings')
|
||||
end
|
||||
|
||||
def set_session_as_public()
|
||||
find('#session-settings-button').trigger(:click)
|
||||
within('#session-settings-dialog') do
|
||||
jk_select("Public", '#session-settings-dialog #session-settings-musician-access')
|
||||
# select('Public', :from => 'session-settings-musician-access')
|
||||
find('#session-settings-dialog-submit').trigger(:click)
|
||||
end
|
||||
# verify it's dismissed
|
||||
page.should have_no_selector('h1', text: 'update session settings')
|
||||
end
|
||||
|
||||
def get_options(selector)
|
||||
find(selector, :visible => false).all('option', :visible => false).collect(&:text).uniq
|
||||
end
|
||||
|
||||
def selected_genres(selector='#session-settings-genre')
|
||||
page.evaluate_script("JK.GenreSelectorHelper.getSelectedGenres('#{selector}')")
|
||||
end
|
||||
|
||||
def random_genre
|
||||
['African',
|
||||
'Ambient',
|
||||
'Asian',
|
||||
'Blues',
|
||||
'Classical',
|
||||
'Country',
|
||||
'Electronic',
|
||||
'Folk',
|
||||
'Hip Hop',
|
||||
'Jazz',
|
||||
'Latin',
|
||||
'Metal',
|
||||
'Pop',
|
||||
'R&B',
|
||||
'Reggae',
|
||||
'Religious',
|
||||
'Rock',
|
||||
'Ska',
|
||||
'Other'].sample
|
||||
end
|
||||
|
||||
def change_session_genre #randomly just change it
|
||||
here = 'select.genre-list'
|
||||
#wait_for_ajax
|
||||
find('#session-settings-button').trigger(:click)
|
||||
find('#session-settings-dialog') # ensure the dialog is visible
|
||||
within('#session-settings-dialog') do
|
||||
wait_for_ajax
|
||||
@new_genre = get_options(here).-(["Select Genre"]).-(selected_genres).sample.to_s
|
||||
jk_select(@new_genre, '#session-settings-dialog select[name="genres"]')
|
||||
wait_for_ajax
|
||||
find('#session-settings-dialog-submit').trigger(:click)
|
||||
end
|
||||
return @new_genre
|
||||
end
|
||||
|
||||
def get_session_genre
|
||||
here = 'select.genre-list'
|
||||
find('#session-settings-button').trigger(:click)
|
||||
wait_for_ajax
|
||||
@current_genres = selected_genres
|
||||
find('#session-settings-dialog-submit').trigger(:click)
|
||||
return @current_genres.join(" ")
|
||||
end
|
||||
|
||||
def find_session_contains?(text)
|
||||
visit "/client#/findSession"
|
||||
wait_for_ajax
|
||||
within('#find-session-form') do
|
||||
expect(page).to have_text(text)
|
||||
end
|
||||
end
|
||||
|
||||
def assert_all_tracks_seen(users=[])
|
||||
users.each do |user|
|
||||
in_client(user) do
|
||||
users.reject {|u| u==user}.each do |other|
|
||||
find('div.track-label', text: other.name)
|
||||
#puts user.name + " is able to see " + other.name + "\'s track"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def view_profile_of user
|
||||
id = user.kind_of?(JamRuby::User) ? user.id : user
|
||||
# assume some user signed in already
|
||||
visit "/client#/profile/#{id}"
|
||||
wait_until_curtain_gone
|
||||
end
|
||||
|
||||
def view_band_profile_of band
|
||||
id = band.kind_of?(JamRuby::Band) ? band.id :
|
||||
band.kind_of?(JamRuby::BandMusician) ? band.bands.first.id : band
|
||||
visit "/client#/bandProfile/#{id}"
|
||||
wait_until_curtain_gone
|
||||
end
|
||||
|
||||
def sidebar_search_for string, category
|
||||
visit "/client#/home"
|
||||
find('#search-input')
|
||||
fill_in "search", with: string
|
||||
sleep 1
|
||||
page.execute_script("JK.Sidebar.searchForInput()")
|
||||
wait_for_ajax
|
||||
jk_select(category, "search_text_type")
|
||||
wait_for_ajax
|
||||
end
|
||||
|
||||
def show_user_menu
|
||||
page.execute_script("$('ul.shortcuts').show()")
|
||||
#page.execute_script("JK.UserDropdown.menuHoverIn()")
|
||||
end
|
||||
|
||||
# wait for the easydropdown version of the specified select element to become visible
|
||||
def wait_for_easydropdown(select)
|
||||
find(select, :visible => false).find(:xpath, 'ancestor::div[contains(@class, "dropdown easydropdown")]')
|
||||
end
|
||||
|
||||
# defaults to enter key (13)
|
||||
def send_key(selector, keycode = 13)
|
||||
keypress_script = "var e = $.Event('keyup', { keyCode: #{keycode} }); jQuery('#{selector}').trigger(e);"
|
||||
page.driver.execute_script(keypress_script)
|
||||
|
||||
end
|
||||
|
||||
def special_characters
|
||||
["?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}"]
|
||||
end
|
||||
|
||||
def garbage length
|
||||
output = ''
|
||||
length.times { output << special_characters.sample }
|
||||
output.slice(0, length)
|
||||
end
|
||||
|
|
@ -4,7 +4,7 @@ unless ENV["LOCAL_DEV"] == "1"
|
|||
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
|
||||
end
|
||||
|
||||
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
|
||||
devenv = ENV["BUILD_NUMBER"].nil?
|
||||
|
||||
if devenv
|
||||
gem 'jam_db', :path=> "../db/target/ruby_package"
|
||||
|
|
|
|||
|
|
@ -138,10 +138,14 @@ require "jam_ruby/models/country"
|
|||
require "jam_ruby/models/region"
|
||||
require "jam_ruby/models/city"
|
||||
require "jam_ruby/models/email_batch"
|
||||
require "jam_ruby/models/email_batch_periodic"
|
||||
require "jam_ruby/models/email_batch_new_musician"
|
||||
require "jam_ruby/models/email_batch_progression"
|
||||
require "jam_ruby/models/email_batch_set"
|
||||
require "jam_ruby/models/email_error"
|
||||
require "jam_ruby/app/mailers/async_mailer"
|
||||
require "jam_ruby/app/mailers/batch_mailer"
|
||||
require "jam_ruby/app/mailers/progress_mailer"
|
||||
require "jam_ruby/models/affiliate_partner"
|
||||
require "jam_ruby/models/chat_message"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
module JamRuby
|
||||
class ProgressMailer < ActionMailer::Base
|
||||
include SendGrid
|
||||
layout "user_mailer"
|
||||
|
||||
sendgrid_category :use_subject_lines
|
||||
sendgrid_unique_args :env => Environment.mode
|
||||
default :from => UserMailer::DEFAULT_SENDER
|
||||
|
||||
def send_reminder(batch_set)
|
||||
user = batch_set.user
|
||||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
sendgrid_substitute(EmailBatchProgression::VAR_FIRST_NAME, [user.first_name])
|
||||
|
||||
mail(:to => user.email,
|
||||
:subject => batch_set.subject,
|
||||
:title => batch_set.title) do |format|
|
||||
format.text { render batch_set.sub_type }
|
||||
format.html { render batch_set.sub_type }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -106,9 +106,9 @@
|
|||
|
||||
sendgrid_recipients([user.email])
|
||||
sendgrid_substitute('@USERID', [user.id])
|
||||
|
||||
sendgrid_unique_args :type => "new_musicians"
|
||||
mail(:to => user.email, :subject => "JamKazam New Musicians in Your Area") do |format|
|
||||
|
||||
mail(:to => user.email, :subject => EmailBatchNewMusician.subject) do |format|
|
||||
format.text
|
||||
format.html
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you have downloaded the free JamKazam application, but you have not yet run the app. You can find other musicians and listen to sessions and recordings on our website, but you need to run the JamKazam application to play with other musicians online. If you are having trouble installing or running the app, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a style="color: #588C98;" href="https://jamkazam.desk.com/">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you have downloaded the free JamKazam application, but you have not yet run the app. You can find other musicians and listen to sessions and recordings on our website, but you need to run the JamKazam application to play with other musicians online. If you are having trouble installing or running the app, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running.
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you have registered as a JamKazam musician, but you have not yet downloaded and started using the free JamKazam application. You can find other musicians and listen to sessions and recordings on our website, but you need the free JamKazam application to play with other musicians online. Please click the link below to go to the download page for the free JamKazam application, or visit our JamKazam support center so that we can help you get up and running.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a style="color: #588C98;" href="http://www.jamkazam.com/downloads">Go to Download Page</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a style="color: #588C98;" href="https://jamkazam.desk.com">Go to Support Center</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you have registered as a JamKazam musician, but you have not yet downloaded and started using the free JamKazam application. You can find other musicians and listen to sessions and recordings on our website, but you need the free JamKazam application to play with other musicians online. Please click the link below to go to the download page for the free JamKazam application, or visit our JamKazam support center so that we can help you get up and running.
|
||||
|
||||
Go to Download Page: http://www.jamkazam.com/downloads
|
||||
|
||||
Go to Support Center: https://jamkazam.desk.com
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you have not yet successfully set up your audio gear and passed the JamKazam latency and input/output audio gear tests. This means that you cannot yet play in online sessions with other musicians. If you are having trouble with this step, please click the link below for a knowledge base article that can help you get past this hurdle. If the test says your audio gear is not fast enough, or if your audio quality sounds poor, or if you are just confused, it’s very likely the tips in this article will help you get things set up and optimized so you can start playing online.
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="http://bit.ly/1i4Uul4">http://bit.ly/1i4Uul4</a>
|
||||
</p>
|
||||
|
||||
<p>And if this knowledge base article does not get you fixed up, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you have not yet successfully set up your audio gear and passed the JamKazam latency and input/output audio gear tests. This means that you cannot yet play in online sessions with other musicians. If you are having trouble with this step, please click the link below for a knowledge base article that can help you get past this hurdle. If the test says your audio gear is not fast enough, or if your audio quality sounds poor, or if you are just confused, it’s very likely the tips in this article will help you get things set up and optimized so you can start playing online.
|
||||
|
||||
http://bit.ly/1i4Uul4
|
||||
|
||||
And if this knowledge base article does not get you fixed up, please visit our JamKazam support center at the link below, and post a request for assistance so that we can help you get up and running:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you haven’t yet played in a JamKazam session with multiple musicians that lasted long enough to be productive or fun. Since that’s the whole point of the service, we wanted to reach out to see if we can help you. Please take a quick look at the suggestions below to see if they help you!
|
||||
</p>
|
||||
|
||||
<p>Find Other Musicians on JamKazam<br />
|
||||
It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. If you click Find Session, you will often not find a good session to join, both due to the number of musicians online at any given time, and also because you won’t see private sessions where groups of musicians don’t want to be interrupted in their sessions.
|
||||
</p>
|
||||
|
||||
<p>If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: <a href="http://www.jamkazam.com/client#/musicians">Go To Musicians Page</a>
|
||||
</p>
|
||||
|
||||
<p>This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session.
|
||||
</p>
|
||||
|
||||
<p>Invite Your Friends to Play<br />
|
||||
One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
</p>
|
||||
|
||||
<p>Troubleshoot Session Problems<br />
|
||||
If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you haven’t yet played in a JamKazam session with multiple musicians that lasted long enough to be productive or fun. Since that’s the whole point of the service, we wanted to reach out to see if we can help you. Please take a quick look at the suggestions below to see if they help you!
|
||||
|
||||
Find Other Musicians on JamKazam
|
||||
It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. If you click Find Session, you will often not find a good session to join, both due to the number of musicians online at any given time, and also because you won’t see private sessions where groups of musicians don’t want to be interrupted in their sessions.
|
||||
|
||||
If you are having trouble getting into sessions, we’d suggest you click the Musicians tile on the home screen of the app or the website: http://www.jamkazam.com/client#/musicians
|
||||
|
||||
This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session.
|
||||
|
||||
Invite Your Friends to Play
|
||||
One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
|
||||
Troubleshoot Session Problems
|
||||
If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you haven’t yet connected with any friends on JamKazam. Connecting with friends is the best way to help you get into sessions with other musicians on JamKazam. Here are a couple of good ways to connect with others.
|
||||
</p>
|
||||
|
||||
<p>Find Other Musicians on JamKazam<br />
|
||||
To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: <a href="http://www.jamkazam.com/client#/musicians">Go To Musicians Page</a>
|
||||
</p>
|
||||
|
||||
<p>This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that you read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session.
|
||||
</p>
|
||||
|
||||
<p>Invite Your Friends to Play<br >
|
||||
One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
</p>
|
||||
|
||||
<p>If you have any trouble, please visit our support center at the link below any time to get help:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com/">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you haven’t yet connected with any friends on JamKazam. Connecting with friends is the best way to help you get into sessions with other musicians on JamKazam. Here are a couple of good ways to connect with others.
|
||||
|
||||
Find Other Musicians on JamKazam
|
||||
To find and connect with other musicians who are already on JamKazam, we’d suggest you click the Musicians tile on the home screen of the app or the website: http://www.jamkazam.com/client#/musicians
|
||||
|
||||
This will display the JamKazam musicians sorted by latency to you - in other words, you can see which musicians have good network connections to you. Any musicians with green and yellow latency scores have good enough connections to support a play session with you. We recommend that you read the profiles of these musicians to find others with shared musical interests and good network connections to you, and then use the Message button to say hi and see if they are interested in playing with you. If they are, use the Connect button to “friend” them on JamKazam, and use the Message button to set up a time to meet online for a session.
|
||||
|
||||
Invite Your Friends to Play
|
||||
One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
|
||||
If you have any trouble, please visit our support center at the link below any time to get help:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you have not invited any of your friends to join you to play together on JamKazam. It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
</p>
|
||||
|
||||
<p>If you have any trouble, please visit our support center at the link below any time to get help:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you have not invited any of your friends to join you to play together on JamKazam. It’s still very early in our company’s development, so we don’t have zillions of users online on our service yet. One of the best ways to connect and play with others is to invite your friends from the “real world” to join you on JamKazam, and then set up a time to meet online and get into a session together. To do this, just go to www.jamkazam.com and sign in. Then move your mouse over your picture or name in the upper right corner of the screen. A menu will be displayed. Click the Invite Friends option, and then you can click Facebook, Google, or Email to easily invite your friends from different services to join you on JamKazam.
|
||||
|
||||
If you have any trouble, please visit our support center at the link below any time to get help:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>JamKazam is a young company/service built through the sweat and commitment of a small group of music-loving techies. Please help us continue to grow the service and attract more musicians to play online by liking and/or following us on Facebook, Twitter, and Google+. Just click the icons below to give us little push, thanks!
|
||||
</p>
|
||||
|
||||
<% [:twitter, :facebook, :google].each do |site| %>
|
||||
<%= link_to(image_tag("http://www.jamkazam.com/assets/content/icon_#{site}.png", :style => "vertical-align:top"), "http://www.jamkazam.com/endorse/@USERID/#{site}?src=email") %>
|
||||
<% end %>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
JamKazam is a young company/service built through the sweat and commitment of a small group of music-loving techies. Please help us continue to grow the service and attract more musicians to play online by liking and/or following us on Facebook, Twitter, and Google+. Just click the icons below to give us little push, thanks!
|
||||
|
||||
<% [:twitter, :facebook, :google].each do |site| %>
|
||||
http://www.jamkazam.com/endorse/@USERID/#{site}?src=email
|
||||
|
||||
<% end %>
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you haven’t yet rated any of your JamKazam sessions as “good”. It may be that you just are not a “rater”, and that is totally fine. But if you are not having good, high quality, productive and fun sessions, we want to help you get there!
|
||||
</p>
|
||||
|
||||
<p>If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:
|
||||
</p>
|
||||
|
||||
<p><a style="color: #588C98;" href="https://jamkazam.desk.com">https://jamkazam.desk.com</a>
|
||||
</p>
|
||||
|
||||
<p>We really want you to be successful and have fun with this new way of playing music with others, so please reach out and let us help you!
|
||||
</p>
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you haven’t yet rated any of your JamKazam sessions as “good”. It may be that you just are not a “rater”, and that is totally fine. But if you are not having good, high quality, productive and fun sessions, we want to help you get there!
|
||||
|
||||
If you are having audio quality problems or other issues when you get into a session, please click the link below to visit our support center, and check the knowledge base articles under the Troubleshooting header to find solutions. And if that doesn’t work, please post a request for assistance in the support center so that we can help you get up and running:
|
||||
|
||||
https://jamkazam.desk.com
|
||||
|
||||
We really want you to be successful and have fun with this new way of playing music with others, so please reach out and let us help you!
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
<p>Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
</p>
|
||||
|
||||
<p>We noticed that you haven’t yet made a recording during any of your JamKazam sessions. Recordings are extra special on JamKazam because:
|
||||
</p>
|
||||
|
||||
<ul><li>Recordings are made both as a master mix and at the track/stem level.</li>
|
||||
<li>You can easily play along with your recordings when your friends aren’t available.</li>
|
||||
<li>You can share your recordings with family, friends and fans via Facebook, Twitter, etc.</li>
|
||||
</ul>
|
||||
|
||||
<!--<p>To understand all of the things you can do with recordings on JamKazam, watch this YouTube tutorial video:<br />
|
||||
www.youtube.com/blahblahblah
|
||||
</p>-->
|
||||
|
||||
<p>-- Team JamKazam
|
||||
</p>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<% provide(:title, @title) %>
|
||||
|
||||
Hello <%= EmailBatchProgression::VAR_FIRST_NAME %> --
|
||||
|
||||
We noticed that you haven’t yet made a recording during any of your JamKazam sessions. Recordings are extra special on JamKazam because:
|
||||
|
||||
- Recordings are made both as a master mix and at the track/stem level.
|
||||
- You can easily play along with your recordings when your friends aren’t available.
|
||||
- You can share your recordings with family, friends and fans via Facebook, Twitter, etc.
|
||||
|
||||
-- Team JamKazam
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
<% provide(:title, 'New JamKazam Musicians in your Area') %>
|
||||
Hi <%= @user.first_name %>,
|
||||
|
||||
<p>The following new musicians have joined JamKazam within the last week, and have Internet connections with low enough latency to you that you can have a good online session together. We'd suggest that you look through the new musicians listed below to see if any match your musical interests, and if so, click through to their profile page on the JamKazam website to send them a message or a request to connect as a JamKazam friend:
|
||||
</p>
|
||||
|
||||
<% link_style = "background-color:#ED3618; margin:0px 8px 0px 8px; border: solid 1px #F27861; outline: solid 2px #ED3618; padding:3px 10px; font-family:Raleway, Arial, Helvetica, sans-serif; font-size:12px; font-weight:300; cursor:pointer; color:#FC9; text-decoration:none;" %>
|
||||
<p>
|
||||
|
|
@ -20,3 +24,8 @@
|
|||
<% end %>
|
||||
</table>
|
||||
</p>
|
||||
<p>There are currently <%= @new_nearby.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: <a href="http://www.jamkazam.com/client#/musicians">http://www.jamkazam.com/client#/musicians</a>.
|
||||
</p>
|
||||
|
||||
<p>Best Regards,</p>
|
||||
Team JamKazam
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
New JamKazam Musicians in your Area
|
||||
|
||||
Hi <%= @user.first_name %>,
|
||||
|
||||
The following new musicians have joined JamKazam within the last week, and have Internet connections with low enough latency to you that you can have a good online session together. We'd suggest that you look through the new musicians listed below to see if any match your musical interests, and if so, click through to their profile page on the JamKazam website to send them a message or a request to connect as a JamKazam friend:
|
||||
|
||||
<% @new_nearby.each do |user| %>
|
||||
<%= user.name %> (http://<%= @host %>/client#/profile/<%= user.id %>)
|
||||
<%= user.location %>
|
||||
<% user.instruments.collect { |inst| inst.description }.join(', ') %>
|
||||
<%= user.biography %>
|
||||
|
||||
<% end %>
|
||||
|
||||
There are currently <%= @new_nearby.size%> musicians on JamKazam with low enough latency Internet connections to you to support a good online session. To see ALL the JamKazam musicians with whom you may want to connect and play, view our Musicians page at: http://www.jamkazam.com/client#/musicians.
|
||||
|
||||
Best Regards,
|
||||
Team JamKazam
|
||||
|
|
|
|||
|
|
@ -78,13 +78,22 @@ FOO
|
|||
self.test_emails.present? && (self.tested? || self.pending?)
|
||||
end
|
||||
|
||||
def deliver_batch
|
||||
self.perform_event('do_batch_run!')
|
||||
def deliver_batch_sets!
|
||||
User.email_opt_in.find_in_batches(batch_size: BATCH_SIZE) do |users|
|
||||
self.email_batch_sets << EmailBatchSet.deliver_set(self.id, users.map(&:id))
|
||||
self.email_batch_sets << (bset = EmailBatchSet.load_set(self, users.map(&:id)))
|
||||
if 'test' == Rails.env
|
||||
BatchMailer.send_batch_email(self.id, bset.user_ids).deliver!
|
||||
else
|
||||
BatchMailer.send_batch_email(self.id, bset.user_ids).deliver
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def deliver_batch
|
||||
self.perform_event('do_batch_run!')
|
||||
self.deliver_batch_sets!
|
||||
end
|
||||
|
||||
def test_count
|
||||
self.test_emails.split(',').count
|
||||
end
|
||||
|
|
@ -195,5 +204,13 @@ FOO
|
|||
})
|
||||
end
|
||||
|
||||
def batch_substitutions(users=[])
|
||||
{}
|
||||
end
|
||||
|
||||
def body_for_users(users=[])
|
||||
self.body
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
module JamRuby
|
||||
class EmailBatchNewMusician < EmailBatchPeriodic
|
||||
|
||||
BATCH_SIZE = 500
|
||||
|
||||
SINCE_WEEKS = 2
|
||||
|
||||
VAR_MUSICIAN_COUNT = "@MUSICIAN_COUNT"
|
||||
VAR_MUSICIAN_TABLE = "@MUSICIAN_TABLE"
|
||||
|
||||
def self.subject
|
||||
"New musicians with good Internet connections to you have joined JamKazam!"
|
||||
end
|
||||
|
||||
def fetch_recipients(since=nil)
|
||||
since ||= Time.now - SINCE_WEEKS.weeks
|
||||
User.geocoded_users
|
||||
.email_opt_in
|
||||
.where(['created_at < ?', since])
|
||||
.find_in_batches(batch_size: EmailBatchNewMusician::BATCH_SIZE) do |users|
|
||||
new_musicians = users.inject({}) do |hh, uu|
|
||||
if 0 < (nearby = uu.nearest_musicians).count
|
||||
hh[uu] = nearby
|
||||
end
|
||||
hh
|
||||
end
|
||||
yield(new_musicians) if block_given?
|
||||
end
|
||||
end
|
||||
|
||||
def deliver_batch_sets!
|
||||
self.opt_in_count = 0
|
||||
sent = 0
|
||||
self.fetch_recipients(self.time_since_last_batch(SINCE_WEEKS)) do |new_musicians|
|
||||
self.opt_in_count += new_musicians.count
|
||||
self.email_batch_sets << (bset = EmailBatchSet.load_set(self, new_musicians.keys.map(&:id)))
|
||||
new_musicians.each do |uu, nearby|
|
||||
UserMailer.new_musicians(uu, nearby).deliver
|
||||
sent += 1
|
||||
end
|
||||
end
|
||||
self.sent_count = sent
|
||||
self.save
|
||||
self.did_batch_run!
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
module JamRuby
|
||||
class EmailBatchPeriodic < EmailBatch
|
||||
self.abstract_class = true
|
||||
|
||||
def time_since_last_batch_query
|
||||
self.class
|
||||
.where(['created_at < ?', self.created_at])
|
||||
.order('created_at DESC')
|
||||
.limit(1)
|
||||
end
|
||||
|
||||
def time_since_last_batch(default_weeks=2)
|
||||
if previous = self.time_since_last_batch_query.first
|
||||
return previous.created_at
|
||||
end
|
||||
Time.now - default_weeks.weeks
|
||||
end
|
||||
|
||||
def fetch_recipients(since=nil)
|
||||
yield([]) if block_given?
|
||||
end
|
||||
|
||||
def self.subject(subtype=nil)
|
||||
''
|
||||
end
|
||||
|
||||
def self.body
|
||||
''
|
||||
end
|
||||
|
||||
def self.new(*args)
|
||||
oo = super
|
||||
oo.body = ''
|
||||
oo.subject = self.subject
|
||||
oo
|
||||
end
|
||||
|
||||
def deliver_batch_sets!
|
||||
end
|
||||
|
||||
def clear_batch_sets!
|
||||
self.email_batch_sets.map(&:destroy)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
module JamRuby
|
||||
class EmailBatchProgression < EmailBatchPeriodic
|
||||
|
||||
BATCH_SIZE = 500
|
||||
SINCE_WEEKS = 2
|
||||
|
||||
SUBTYPES = [:client_notdl, # Registered Musician Has Not Downloaded Client
|
||||
:client_dl_notrun, # Registered Musician Has Downloaded Client But Not Yet Run It
|
||||
:client_run_notgear, # Registered Musician Has Run Client But Not Successfully Qualified Audio Gear
|
||||
:gear_notsess, # Registered Musician Has Successfully Qualified Audio Gear But Has Not Participated in a ‘Real’ Session
|
||||
:sess_notgood, # Registered Musician Has Participated In a "Real" Session But Has Not Had a "Good" Session
|
||||
:sess_notrecord, # Registered Musician Has Participated In a "Real" Session But Has Not Made a Recording
|
||||
:reg_notinvite, # Registered Musician Has Not Invited Friends to Join JamKazam
|
||||
:reg_notconnect, # Registered Musician Has Not Connected with any Friends on JamKazam
|
||||
:reg_notlike, # Registered Musician Has Not Liked Jamkazam
|
||||
]
|
||||
|
||||
SUBTYPE_METADATA = {
|
||||
:client_notdl => {
|
||||
:subject => "Get the free JamKazam app now and start playing with others!",
|
||||
:title => "Download the Free JamKazam App"
|
||||
},
|
||||
:client_dl_notrun => {
|
||||
:subject => "Having trouble running the JamKazam application?",
|
||||
:title => "Running the JamKazam App"
|
||||
},
|
||||
:client_run_notgear => {
|
||||
:subject => "Having trouble setting up your audio gear for JamKazam?",
|
||||
:title => "Setting Up and Qualifying Your Audio Gear on JamKazam"
|
||||
},
|
||||
:gear_notsess => {
|
||||
:subject => "Having trouble getting into a session with other musicians?",
|
||||
:title => "Tips on Getting into Sessions with Other Musicians"
|
||||
},
|
||||
:sess_notgood => {
|
||||
:subject => "Have you played in a “good” session on JamKazam yet?",
|
||||
:title => "Having a Good Session on JamKazam"
|
||||
},
|
||||
:reg_notinvite => {
|
||||
:subject => "Invite your friends to JamKazam, best way to play online!",
|
||||
:title => "Invite Your Friends to Come and Play with You"
|
||||
},
|
||||
:reg_notconnect => {
|
||||
:subject => "Make friends on JamKazam and play more music!",
|
||||
:title => "Connecting with Friends on JamKazam"
|
||||
},
|
||||
:reg_notlike => {
|
||||
:subject => "Please give us a LIKE!",
|
||||
:title => "Like/Follow JamKazam"
|
||||
},
|
||||
:sess_notrecord => {
|
||||
:subject => "Want to make recordings during your JamKazam sessions?",
|
||||
:title => "Making & Sharing Recordings on JamKazam"
|
||||
},
|
||||
}
|
||||
|
||||
def self.subject(subtype=nil)
|
||||
SUBTYPE_METADATA[subtype][:subject] if subtype
|
||||
end
|
||||
|
||||
def self.title(subtype=nil)
|
||||
SUBTYPE_METADATA[subtype][:title] if subtype
|
||||
end
|
||||
|
||||
def self.subtype_trigger_interval(subtype)
|
||||
[:reg_notlike, :sess_notrecord].include?(subtype) ? [7,14,21] : [2,5,14]
|
||||
end
|
||||
|
||||
def self.days_past_for_trigger_index(subtype, idx)
|
||||
self.subtype_trigger_interval(subtype)[idx]
|
||||
end
|
||||
|
||||
def days_diff(tidx)
|
||||
self.class.days_past_for_trigger_index(self.sub_type,tidx) - self.class.days_past_for_trigger_index(self.sub_type, tidx - 1)
|
||||
end
|
||||
|
||||
def days_past_for_trigger_index(idx)
|
||||
self.class.subtype_trigger_interval(self.sub_type)[idx]
|
||||
end
|
||||
|
||||
def make_set(uu, trigger_idx)
|
||||
EmailBatchSet.progress_set(self, uu, trigger_idx)
|
||||
end
|
||||
|
||||
def trigger_date_constraint(trigger_idx, tbl='tt')
|
||||
intervals = self.class.subtype_trigger_interval(self.sub_type)
|
||||
date_constraint = (Time.now - intervals[trigger_idx].days + 1.hour).strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
case self.sub_type.to_sym
|
||||
when :client_notdl, :reg_notconnect, :reg_notinvite, :reg_notlike
|
||||
return "#{tbl}.created_at < '#{date_constraint}'"
|
||||
when :client_dl_notrun
|
||||
return "#{tbl}.first_downloaded_client_at < '#{date_constraint}'"
|
||||
when :client_run_notgear
|
||||
return "#{tbl}.first_ran_client_at < '#{date_constraint}'"
|
||||
when :gear_notsess
|
||||
return "#{tbl}.first_certified_gear_at < '#{date_constraint}'"
|
||||
when :sess_notgood
|
||||
return "#{tbl}.first_real_music_session_at < '#{date_constraint}'"
|
||||
when :sess_notrecord
|
||||
return "#{tbl}.first_real_music_session_at < '#{date_constraint}'"
|
||||
end
|
||||
end
|
||||
|
||||
def progress_column_constraint(tbl='tt')
|
||||
case self.sub_type.to_sym
|
||||
when :client_notdl
|
||||
return "#{tbl}.first_downloaded_client_at IS NULL"
|
||||
when :client_dl_notrun
|
||||
return "#{tbl}.first_downloaded_client_at IS NOT NULL AND #{tbl}.first_ran_client_at IS NULL"
|
||||
when :client_run_notgear
|
||||
return "#{tbl}.first_ran_client_at IS NOT NULL AND #{tbl}.first_certified_gear_at IS NULL"
|
||||
when :gear_notsess
|
||||
return "#{tbl}.first_certified_gear_at IS NOT NULL AND #{tbl}.first_real_music_session_at IS NULL"
|
||||
when :sess_notgood
|
||||
return "#{tbl}.first_real_music_session_at IS NOT NULL AND #{tbl}.first_good_music_session_at IS NULL"
|
||||
when :sess_notrecord
|
||||
return "#{tbl}.first_real_music_session_at IS NOT NULL AND #{tbl}.first_recording_at IS NULL"
|
||||
when :reg_notinvite
|
||||
return "#{tbl}.first_invited_at IS NULL"
|
||||
when :reg_notconnect
|
||||
return "#{tbl}.first_friended_at IS NULL"
|
||||
when :reg_notlike
|
||||
return "#{tbl}.first_social_promoted_at IS NULL"
|
||||
end
|
||||
''
|
||||
end
|
||||
|
||||
def fetch_recipients(trigger_idx=0, per_page=BATCH_SIZE)
|
||||
fetched = []
|
||||
offset = 0
|
||||
if 0==trigger_idx
|
||||
prev_date_sql = 'tt.prev_trigger_date IS NULL'
|
||||
else
|
||||
prev_date_sql = "tt.prev_trigger_date + interval '#{self.days_diff(trigger_idx)} days' <= '#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}'"
|
||||
end
|
||||
countsql =<<SQL
|
||||
SELECT COUNT(*)
|
||||
FROM (SELECT "users".*,
|
||||
(SELECT COALESCE(MAX(ebs.trigger_index),-1)
|
||||
FROM email_batch_sets ebs
|
||||
WHERE
|
||||
ebs.sub_type = '#{self.sub_type}' AND
|
||||
ebs.user_id = users.id
|
||||
) AS tidx,
|
||||
(SELECT created_at
|
||||
FROM email_batch_sets ebs
|
||||
WHERE
|
||||
ebs.sub_type = '#{self.sub_type}' AND
|
||||
ebs.user_id = users.id AND trigger_index = #{trigger_idx - 1}
|
||||
) AS prev_trigger_date
|
||||
FROM users) tt
|
||||
WHERE
|
||||
tt."subscribe_email" = 't' AND
|
||||
tt."musician" = 't' AND
|
||||
(#{progress_column_constraint}) AND
|
||||
(#{self.trigger_date_constraint(trigger_idx)}) AND
|
||||
tt.tidx = #{trigger_idx - 1} AND
|
||||
#{prev_date_sql}
|
||||
SQL
|
||||
num_users = User.count_by_sql(countsql)
|
||||
loops = (num_users / per_page) + (num_users % per_page) - 1
|
||||
0.upto(loops) do |nn|
|
||||
offset = nn * per_page
|
||||
sql =<<SQL
|
||||
SELECT tt.*
|
||||
FROM (SELECT "users".*,
|
||||
(SELECT COALESCE(MAX(ebs.trigger_index),-1)
|
||||
FROM email_batch_sets ebs
|
||||
WHERE
|
||||
ebs.sub_type = '#{self.sub_type}' AND
|
||||
ebs.user_id = users.id
|
||||
) AS tidx,
|
||||
(SELECT created_at
|
||||
FROM email_batch_sets ebs
|
||||
WHERE
|
||||
ebs.sub_type = '#{self.sub_type}' AND
|
||||
ebs.user_id = users.id AND trigger_index = #{trigger_idx - 1}
|
||||
) AS prev_trigger_date
|
||||
FROM users) tt
|
||||
WHERE
|
||||
tt."subscribe_email" = 't' AND
|
||||
tt."musician" = 't' AND
|
||||
(#{progress_column_constraint}) AND
|
||||
(#{self.trigger_date_constraint(trigger_idx)}) AND
|
||||
tt.tidx = #{trigger_idx - 1} AND
|
||||
#{prev_date_sql}
|
||||
ORDER BY tt.id
|
||||
ASC LIMIT #{per_page}
|
||||
OFFSET #{offset}
|
||||
SQL
|
||||
users = User.find_by_sql(sql)
|
||||
block_given? ? yield(users) : fetched.concat(users)
|
||||
end
|
||||
fetched
|
||||
end
|
||||
|
||||
def deliver_batch_sets!
|
||||
self.opt_in_count = 0
|
||||
sent = 0
|
||||
3.times do |trigger_idx|
|
||||
self.fetch_recipients(trigger_idx) do |users|
|
||||
users.each do |uu|
|
||||
self.email_batch_sets << (bset = self.make_set(uu, trigger_idx))
|
||||
ProgressMailer.send_reminder(bset).deliver
|
||||
sent += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
self.sent_count = sent
|
||||
self.save
|
||||
self.did_batch_run!
|
||||
end
|
||||
|
||||
def self.send_progress_batch
|
||||
self::SUBTYPES.collect do |stype|
|
||||
ebatch = self.create
|
||||
ebatch.update_attribute(:sub_type, stype.to_s)
|
||||
ebatch
|
||||
end.each do |ebatch|
|
||||
ebatch.deliver_batch
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -3,21 +3,53 @@ module JamRuby
|
|||
self.table_name = "email_batch_sets"
|
||||
|
||||
belongs_to :email_batch, :class_name => 'JamRuby::EmailBatch'
|
||||
belongs_to :user, :class_name => 'JamRuby::User'
|
||||
|
||||
def self.deliver_set(batch_id, user_ids)
|
||||
def self.load_set(batch, user_ids)
|
||||
bset = self.new
|
||||
bset.email_batch_id = batch_id
|
||||
bset.email_batch_id = batch.id
|
||||
bset.user_ids = user_ids.join(',')
|
||||
bset.started_at = Time.now
|
||||
bset.batch_count = user_ids.size
|
||||
bset.save!
|
||||
|
||||
if 'test' == Rails.env
|
||||
BatchMailer.send_batch_email(bset.email_batch_id, user_ids).deliver!
|
||||
else
|
||||
BatchMailer.send_batch_email(bset.email_batch_id, user_ids).deliver
|
||||
end
|
||||
bset
|
||||
end
|
||||
|
||||
def self.progress_set(batch, user, trigger_idx)
|
||||
bset = self.new
|
||||
bset.email_batch = batch
|
||||
bset.user = user
|
||||
bset.started_at = Time.now
|
||||
bset.batch_count = 1
|
||||
bset.trigger_index = trigger_idx
|
||||
bset.sub_type = batch.sub_type
|
||||
bset.save!
|
||||
bset
|
||||
end
|
||||
|
||||
def subject
|
||||
unless sub_type.blank?
|
||||
return EmailBatchProgression.subject(self.sub_type.to_sym)
|
||||
end
|
||||
''
|
||||
end
|
||||
|
||||
def title
|
||||
unless sub_type.blank?
|
||||
return EmailBatchProgression.title(self.sub_type.to_sym)
|
||||
end
|
||||
''
|
||||
end
|
||||
|
||||
def previous_trigger_date
|
||||
return nil if 0 == self.trigger_index.to_i || self.user_id.nil?
|
||||
self.class
|
||||
.where(['email_batch__id = ? AND user_id = ? AND sub_type = ? AND trigger_index = ?',
|
||||
self.email_batch_id, self.user_id, self.sub_type, self.trigger_index - 1])
|
||||
.pluck(:created_at)
|
||||
.limit(1)
|
||||
.first
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1170,6 +1170,11 @@ module JamRuby
|
|||
.limit(3)
|
||||
end
|
||||
|
||||
def nearest_musicians
|
||||
# FIXME: replace with Scotts scoring query
|
||||
Search.new_musicians(self, Time.now - 1.week)
|
||||
end
|
||||
|
||||
def self.deliver_new_musician_notifications(since_date=nil)
|
||||
since_date ||= Time.now-1.week
|
||||
# todo scott return musicians with locidispid not null
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
module JamRuby
|
||||
class UserProgressEmailer
|
||||
extend Resque::Plugins::LonelyJob
|
||||
|
||||
@queue = :scheduled_user_progress_emailer
|
||||
@@log = Logging.logger[UserProgressEmailer]
|
||||
|
||||
def self.perform
|
||||
@@log.debug("waking up")
|
||||
EmailBatchProgression.send_progress_batch
|
||||
@@log.debug("done")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -445,6 +445,12 @@ FactoryGirl.define do
|
|||
test_emails 4.times.collect { Faker::Internet.safe_email }.join(',')
|
||||
end
|
||||
|
||||
factory :email_batch_new_musician, :class => JamRuby::EmailBatchNewMusician do
|
||||
end
|
||||
|
||||
factory :email_batch_progression, :class => JamRuby::EmailBatchProgression do
|
||||
end
|
||||
|
||||
factory :notification, :class => JamRuby::Notification do
|
||||
|
||||
factory :notification_text_message do
|
||||
|
|
|
|||
|
|
@ -1,18 +1,464 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe EmailBatch do
|
||||
let (:email_batch) { FactoryGirl.create(:email_batch) }
|
||||
|
||||
before(:each) do
|
||||
BatchMailer.deliveries.clear
|
||||
after(:each) do
|
||||
Timecop.return
|
||||
end
|
||||
|
||||
it 'has test emails setup' do
|
||||
expect(email_batch.test_emails.present?).to be true
|
||||
expect(email_batch.pending?).to be true
|
||||
describe 'all users' do
|
||||
|
||||
# before { pending }
|
||||
|
||||
users = email_batch.test_users
|
||||
expect(email_batch.test_count).to eq(users.count)
|
||||
let (:email_batch) { FactoryGirl.create(:email_batch) }
|
||||
|
||||
before(:each) do
|
||||
BatchMailer.deliveries.clear
|
||||
end
|
||||
|
||||
it 'has test emails setup' do
|
||||
|
||||
expect(email_batch.test_emails.present?).to be true
|
||||
expect(email_batch.pending?).to be true
|
||||
|
||||
users = email_batch.test_users
|
||||
expect(email_batch.test_count).to eq(users.count)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'new musician' do
|
||||
before { pending }
|
||||
|
||||
let (:new_musician_batch) { FactoryGirl.create(:email_batch_new_musician) }
|
||||
|
||||
before(:each) do
|
||||
@u1 = FactoryGirl.create(:user, :lat => 37.791649, :lng => -122.394395, :email => 'jonathan@jamkazam.com', :subscribe_email => true, :created_at => Time.now - 3.weeks)
|
||||
@u2 = FactoryGirl.create(:user, :lat => 37.791649, :lng => -122.394395, :subscribe_email => true)
|
||||
@u3 = FactoryGirl.create(:user, :lat => 37.791649, :lng => -122.394395, :subscribe_email => false, :created_at => Time.now - 3.weeks)
|
||||
@u4 = FactoryGirl.create(:user, :lat => 37.791649, :lng => -122.394395, :subscribe_email => true, :created_at => Time.now - 3.weeks)
|
||||
end
|
||||
|
||||
it 'find new musicians with good score' do
|
||||
new_musician_batch.fetch_recipients do |new_musicians|
|
||||
expect(new_musicians.count).to eq(2)
|
||||
num = (new_musicians.keys.map(&:id) - [@u1.id, @u4.id]).count
|
||||
expect(num).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
it 'cycles through states properly' do
|
||||
new_musician_batch.deliver_batch
|
||||
expect(UserMailer.deliveries.length).to eq(2)
|
||||
new_musician_batch.reload
|
||||
expect(new_musician_batch.delivered?).to eq(true)
|
||||
expect(new_musician_batch.sent_count).to eq(2)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'user progress' do
|
||||
|
||||
# before { pending }
|
||||
|
||||
def handles_new_users(ebatch, user)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = user.created_at + ebatch.days_past_for_trigger_index(0).days
|
||||
Timecop.travel(dd)
|
||||
vals = [1,0,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 0)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(1).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,1,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 1)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(2).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,0,1]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 2)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
end
|
||||
|
||||
def handles_existing_users(ebatch, user)
|
||||
vals = [1,0,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
|
||||
dd = user.created_at + ebatch.days_past_for_trigger_index(0).days
|
||||
Timecop.travel(dd)
|
||||
ebatch.make_set(user, 0)
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(1).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,1,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 1)
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(2).days
|
||||
Timecop.travel(dd)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(1)
|
||||
ebatch.make_set(user, 2)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(0)
|
||||
|
||||
dd = dd + 1
|
||||
Timecop.travel(dd)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(0)
|
||||
end
|
||||
|
||||
def skips_some_days(ebatch, user)
|
||||
dd = user.created_at + ebatch.days_past_for_trigger_index(1).days
|
||||
Timecop.travel(dd)
|
||||
vals = [1,0,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 0)
|
||||
2.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(0) }
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(1).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,1,0]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 1)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(0)
|
||||
|
||||
dd = dd + ebatch.days_past_for_trigger_index(2).days
|
||||
Timecop.travel(dd)
|
||||
vals = [0,0,1]
|
||||
3.times { |nn| expect(ebatch.fetch_recipients(nn).count).to eq(vals[nn]) }
|
||||
ebatch.make_set(user, 2)
|
||||
expect(ebatch.fetch_recipients(2).count).to eq(0)
|
||||
end
|
||||
|
||||
def loops_bunch_of_users(ebatch, users)
|
||||
expect(ebatch.fetch_recipients(0,5).count).to eq(0)
|
||||
dd = users[0].created_at + ebatch.days_past_for_trigger_index(0).days
|
||||
Timecop.travel(dd)
|
||||
expect(ebatch.fetch_recipients(0,5).count).to eq(20)
|
||||
users.each { |uu| ebatch.make_set(uu, 0) }
|
||||
expect(ebatch.fetch_recipients(0,5).count).to eq(0)
|
||||
users.map &:destroy
|
||||
end
|
||||
|
||||
def sends_one_email(existing_user, ebatch)
|
||||
ProgressMailer.deliveries.clear
|
||||
ebatch.deliver_batch
|
||||
expect(ProgressMailer.deliveries.length).to eq(1)
|
||||
end
|
||||
|
||||
describe 'client_notdl' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :client_notdl)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user) }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => Time.now - (2 * batchp.days_past_for_trigger_index(2)).days)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'client_dl_notrun' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :client_dl_notrun)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_downloaded_client_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_downloaded_client_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_downloaded_client_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'client_run_notgear' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :client_run_notgear)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_ran_client_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_ran_client_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_ran_client_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'gear_notsess' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :gear_notsess)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_certified_gear_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_certified_gear_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_certified_gear_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'sess_notgood' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :sess_notgood)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_real_music_session_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_real_music_session_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_real_music_session_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'sess_notrecord' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :sess_notrecord)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user, :first_real_music_session_at => Time.now) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past,
|
||||
:first_real_music_session_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user, :first_real_music_session_at => Time.now) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'reg_notinvite' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :reg_notinvite)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'reg_notconnect' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :reg_notconnect)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'reg_notlike' do
|
||||
# before { pending }
|
||||
let(:batchp) {
|
||||
FactoryGirl.create(:email_batch_progression, :sub_type => :reg_notlike)
|
||||
}
|
||||
let(:user_) { FactoryGirl.create(:user) }
|
||||
let(:date_in_past) { Time.now - (2 * batchp.days_past_for_trigger_index(2)).days }
|
||||
let(:user_existing) {
|
||||
FactoryGirl.create(:user,
|
||||
:created_at => date_in_past)
|
||||
}
|
||||
after(:each) do
|
||||
batchp.clear_batch_sets!
|
||||
Timecop.return
|
||||
end
|
||||
it 'sends one email' do
|
||||
sends_one_email(user_existing, batchp)
|
||||
end
|
||||
it 'handles new users' do
|
||||
handles_new_users(batchp, user_)
|
||||
end
|
||||
it 'handles existing users' do
|
||||
handles_existing_users(batchp, user_existing)
|
||||
end
|
||||
it 'skips some days' do
|
||||
skips_some_days(batchp, user_)
|
||||
end
|
||||
it 'loops bunch of users' do
|
||||
users = []
|
||||
20.times { |nn| users << FactoryGirl.create(:user) }
|
||||
loops_bunch_of_users(batchp, users)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ unless ENV["LOCAL_DEV"] == "1"
|
|||
end
|
||||
# Look for $WORKSPACE, otherwise use "workspace" as dev path.
|
||||
|
||||
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
|
||||
devenv = ENV["BUILD_NUMBER"].nil? # Jenkins sets a build number environment variable
|
||||
|
||||
if devenv
|
||||
gem 'jam_db', :path=> "../db/target/ruby_package"
|
||||
|
|
|
|||
|
|
@ -371,8 +371,8 @@ class UsersController < ApplicationController
|
|||
|
||||
def endorse
|
||||
if uu = current_user ||
|
||||
uu = User.where(['id = ? AND first_liked_us IS NULL',params[:id]]).limit(1).first
|
||||
uu.first_liked_us = Time.now
|
||||
uu = User.where(['id = ? AND first_social_promoted_at IS NULL',params[:id]]).limit(1).first
|
||||
uu.first_social_promoted_at = Time.now
|
||||
uu.save!
|
||||
end if params[:id].present? && (service=params[:service]).present?
|
||||
|
||||
|
|
|
|||
|
|
@ -24,3 +24,7 @@ EmailErrorCollector:
|
|||
class: "JamRuby::EmailErrorCollector"
|
||||
description: "Collects sendgrid email errors"
|
||||
|
||||
UserProgressEmailer:
|
||||
cron: "30 21 * * *"
|
||||
class: "JamRuby::UserProgressEmailer"
|
||||
description: "Sends periodic user progress emails"
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ db_config = YAML::load(File.open('config/database.yml'))["test"]
|
|||
|
||||
|
||||
bputs "before recreate db"
|
||||
SpecDb::recreate_database(db_config) unless ENV["TEST_WWW"] == "1"
|
||||
SpecDb::recreate_database(db_config)
|
||||
|
||||
bputs "before connect db"
|
||||
ActiveRecord::Base.establish_connection(YAML::load(File.open('config/database.yml'))["test"])
|
||||
|
|
@ -162,9 +162,6 @@ bputs "before register capybara"
|
|||
config.filter_run_excluding slow: true unless ENV['RUN_SLOW_TESTS'] == "1" || ENV['SLOW'] == "1" || ENV['ALL_TESTS'] == "1"
|
||||
config.filter_run_excluding aws: true unless ENV['RUN_AWS_TESTS'] == "1" || ENV['AWS'] == "1" || ENV['ALL_TESTS'] == "1"
|
||||
|
||||
# by default, do not run production web tests -- even when "ALL_TESTS" is desired
|
||||
config.filter_run_excluding test_www: true unless ENV['TEST_WWW'] == "1"
|
||||
|
||||
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
||||
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ unless ENV['LOCAL_DEV'] == '1'
|
|||
end
|
||||
|
||||
# Look for $WORKSPACE, otherwise use "workspace" as dev path.
|
||||
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
|
||||
devenv = ENV["BUILD_NUMBER"].nil?
|
||||
|
||||
if devenv
|
||||
gem 'jam_db', :path=> "../db/target/ruby_package"
|
||||
|
|
|
|||
Loading…
Reference in New Issue