working and tested
This commit is contained in:
+3
-2
@@ -1,9 +1,10 @@
|
||||
before-install:
|
||||
- export TRAVIS_COMMIT_MSG="$(git log --format=%B --no-merges -n 1)"
|
||||
env:
|
||||
env:
|
||||
global:
|
||||
- secure: jVZVvtvRSEHDoG6W3Ptq0kw19ZnJTYIQrKZ0SxhV2CQMwgKY5nDsQXUqbfPpQktPOKyLeMb2DljwkGRC6UZ+j6UEy+O3+MS5YBrE6svkcaBgx8A4ck+S4rddKAzf6rpB4h+EfqdVXNknY0wulUy1vc2oCM9o/P1MMu8jOqeSQglLemFZdQS4DHLy1zecjY2ovX18sql+u995r8tDmoNEt00zrZo+UmWN9TP0eag2/+ZHSLWFpWlZF2E1HctZ+iFN9KgcZ277QbGKcIOXYcc5IbyHdwuG+EHU4sH9/d3d687g8GbeTpQBynO/SwQKs/6uATQrYgtvq47fbPKYjk025awXmXvVskwZg9obKsOT3F+NA4xiyzgnQ/RnW+FOP4CUKUn7eXG64c86PFG+cUdLQNmM7MKOyb3dzdN2bUQX1kUx3ZBCV2gWNf5Hhod2ntvC7zY7naN4fV9wRjQJ19ZXSUKpZJOl4iPQQTurFs75Mct09R4Z6UXFlcVyBe2Wj3J1G9SiJOMM0vGvyDbdt9rbkD9ahIbHHK7X8c4xpwZczqq5hJoNKnltdKZf/BOOmfUW9PB4Nkg9kbc7/Had/6Q3xHYzo5LjRXNvVIan2dgIlUkSzGfIskS+I0cYrR1rwa8w7e7dzyDf1WAcHOi6aVYPDkMwjqOSDTXua/FyJXVCGHk=
|
||||
- secure: I4Dsa7rN1p1RMCt7K2ElPofcfgJoEieiWihxI4MNkmcAD33Wz2O1HEp0dfzBS6lTPulb6MfC6XvWLAtNgfroYV/C28Wu1sNn4M7GzqdD0MZ7S9mfHWl+vUlp+1ptV8bUPOez3vk2R41wEG6GIp1EIr/xuhfgsMikg5IkQST/OOMKagMALM0aQVrewaiORNjbxoCpSf4zZ8dyE5kLAe1ZICRv6DgZ+vJjCosikp/lYauqlxiQdzio3RkBa049xu7rCBipbvkl+k5CLxdwHtfw60UaGj9/FKjqrZza+45TevaUwxehhSD6GkoPkbw/h+7VPj+exZ7RDmT7JrDinTm2sDNsz2FDA0DSs0HdOV6+K48tAUTEpGR+BUedtgXomE6Tt0Evr4qNxSpgns+vQ4dlSLoW/AHNxVUQ5EtIcpPnPs26hlbn66rFLZriyqMndImHh5XqhoXvsHEI1467ozd2TqS3n13GORz6EwgzCrY4OGBJiI35RL2RJv+OXcTsTY3hI4wFP5sIdFuilTTwNPIuUKLLTkNbjAlPA+/8lmQXwrOED2bNWXo+iBfRd+PiYHm3KXCZRFJSeoJbDd0kmxd3i6RQEh1oZKp7keJ7UIAIgwZ+girNI6mSkGiHteqToJnLsk4sFf5reA58tdfFa9bQbUsXrezfwnnFhOnEkVCuqwU=
|
||||
- secure: OVCBOhg2IilVc3qjj+DdCrewXxH4LqB7pyQAtVOP2nVegV2ZYVD9AZjjSp2gcd3GgTDWyFNbjta9qwn1i3aVFt+TfH2U5NMjleZTlWPgBCN9XJPQI3SNiMzYDI+qcEWcbNSRkSKFx5xFI9s3QaB9wWOMy0/uNSMo8OokMWMUZjICGMXyN0xYGbUskGDff4BBge13Qjboc2c24wTU5WvlGT8mSy0g10AofbYDI5LkDnVmbqSv0KcxzVlUovFnqtOFphzOZiLLm4X64WJKcHVsQbImNpfSGNFnTpBDKmom0CVs19sl+bznPtR/6/n0vQDmm6Wfu9d5JuOYGOMapUpWmwRXMRA9MSSDjhSGtrm01G+/crRdFO+00vSBAxZjocpWldX5hrQGNbjhw+CU+BKw57T3vZ+5lpb4DlAmU9TbplZ10k54D06Z8lOtQN11ZAXkrhccVIdGfYzDwcg21xvkR+SVoq8+np/9ex4ps5gBpsDWAQ5pHBDp6sEX9JSzRZQFR3xuSB/zkwcTe2mozaqzr9rRc5A83M/OOKmHoPyuNI8TnzMQQP2Hl35W15ab5anbhpUmpEhlea8gQsC8ktEgYPfL+x75XwhY/ooPUtSqIH7wZYJms7niXeLicamws4GpM65w02G6z5kMEAH1wJkEY458PvVlWsIeKDO1Hn1YC7k=
|
||||
- secure: Nf6BEvDEr5O4l0J+G00TfPKuTCn15d+d9YKR8DkqMkKpnZkZO0M+PsbeXe6fZcxuXcTFvOYxFSv/YaEVNe+IUiHHpExdrk7lxpuKN4gI0oSWXojtKKkt1GZ85vZDL3vnAHYKT07uEZNHsONziNuR3Dy7GeGjN/irb9OgmXoiXmVciKZiuNP1q5Msr409V6BWMvFx2qL5M7eDzjHW/Oh7LiFsNFPcrUhzHe8SqUhOTlfkfz3YpZvh80NCwnfiZNP0yVBRIpHZDFnzgTZimNwuS3ya479FBR6Oyt8gKOe7VoiLfef+/kyAMy8moXO9722bi4nay4ic7MJ0uRBeETgEtgdby/nk/5toJvO3nmX0JSGc24rJqLZbAjoXjJlg2gAaCscsNaQGFh5VJ4Ih4CTTc1s9/D4LpgkcX4/rahq5WK89XHY6ps1LCqskC/5NUoNy1844gFmk3SzZq6/oOpVQAA/R50wGj03SqGZqaoEtjf2xhBtiSsw7zRhMMs/FR/HWhGjVgquUX+y74B437T0csddBX/BIsA1ThjV3ENiJPSJwQnbDuZUBE7WhnRv7S6lIP0F/duW3DqxMpuojZdSCiazIaTSljggh7aavib1EcZy4z1Gpslcgov9eKlVnX4/BVos2wwbRvj5Zt3+ku8fSienoqu/8a5QudbhJm5SbySM=
|
||||
addons:
|
||||
sauce_connect: true
|
||||
language: node_js
|
||||
|
||||
@@ -13,8 +13,7 @@ task 'build', 'build project', (options) ->
|
||||
exec 'node_modules/.bin/coffee -bcm -o .test/ test/'
|
||||
|
||||
task 'watch', 'watch for changes and recompile project', ->
|
||||
exec 'node_modules/.bin/coffee -bcmw -o lib/ src/'
|
||||
exec 'node_modules/.bin/coffee -bcmw -o .test test/'
|
||||
exec 'node_modules/.bin/bebop'
|
||||
|
||||
task 'publish', 'publish project', (options) ->
|
||||
newVersion = options.version ? 'patch'
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
exec = require('executive').interactive
|
||||
|
||||
requisite = 'node_modules/.bin/requisite -g'
|
||||
|
||||
compile = ->
|
||||
exec 'node_modules/.bin/coffee -bcm -o lib/ src/'
|
||||
exec 'node_modules/.bin/requisite src/index.coffee -o inform.js'
|
||||
exec 'node_modules/.bin/requisite src/index.coffee -m -o inform.min.js'
|
||||
|
||||
module.exports =
|
||||
port: 4242
|
||||
|
||||
cwd: process.cwd()
|
||||
|
||||
exclude: [
|
||||
/css/
|
||||
/lib/
|
||||
/node_modules/
|
||||
/vendor/
|
||||
]
|
||||
|
||||
compilers:
|
||||
coffee: (src) ->
|
||||
if /^src/.test src
|
||||
compile()
|
||||
|
||||
if /src\/index.coffee/.test src
|
||||
compile()
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
(function(e){function t(e,n){if({}.hasOwnProperty.call(t.cache,e))return t.cache[e];if("function"==typeof n)return void t.load(e,n);var r=t.resolve(e);if(!r)throw new Error("Failed to resolve module "+e);var i={id:e,require:t,filename:e,exports:{},loaded:!1,parent:null,children:[]},o=e.slice(0,e.lastIndexOf("/")+1);return t.cache[e]=i.exports,r.call(i.exports,i,i.exports,o,e),i.loaded=!0,t.cache[e]=i.exports}t.modules={},t.cache={},t.resolve=function(e){return{}.hasOwnProperty.call(t.modules,e)?t.modules[e]:void 0},t.define=function(e,n){t.modules[e]=n},t.define("little-emitter/emitter",function(e,t,n,r){!function(n,r){"function"==typeof define&&define.amd?define(r):"object"==typeof t?e.exports=r():r(n)}(this,function(e){"use strict";function t(e){return e?(e._events={},n(e,i)):void(this._events={})}function n(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e}function r(e){var t=[];for(var n in e)e.hasOwnProperty(n)&&(t=t.concat(e[n]));return t}var i,o=Array.prototype.slice;return i=t.prototype,i.on=i.addEventListener=function(e,t){return(this._events[e]=this._events[e]||[]).push(t),this},i.one=i.once=function(e,t){var n=function(){this.off(e,n),t.apply(this,arguments)};return n.fn=t,this.on(e,n)},i.off=i.removeAllListners=i.removeEventListener=function(e,t){var n=this._events[e];if(0===arguments.length)this._events={};else if(1===arguments.length)delete this._events[e];else if(n){for(var r,i=0;i<n.length;i++)if(r=n[i],r===t||r.fn===t){n.splice(i,1);break}n.length||delete this._events[e]}return this},i.emit=i.trigger=function(e){var t=this._events[e];if(!t)return!1;for(var n=0,r=t.length;r>n;n++)t[n].apply(this,o.call(arguments,1));return!0},i.listeners=function(e){return e?this._events[e]?this._events[e]:[]:r(this._events)},e?void(e.Emitter=t):t})}),t.define("./index",function(e,n,r,i){var o;o=t("little-emitter/emitter"),function(){var e,t,n,r,i;return e=new o,n=function(e){var t,n;return n=document.getElementsByTagName(e),t=n[t.length-1]},i=n("script"),t=n("form"),r=function(){return t.getElementsByTagName("input")},document.addEventListener?document.addEventListener("DOMContentLoaded",r,!1):document.attachEvent&&document.attachEvent("onreadystatechange",function(){return"complete"===document.readyState?r():void 0}),window.addEventListener?window.addEventListener("load",r,!1):window.attachEvent&&window.attachEvent("onload",r),e}()}),t("./index")}).call(this,this);
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
(function(e){function t(e,n){if({}.hasOwnProperty.call(t.cache,e))return t.cache[e];if("function"==typeof n)return void t.load(e,n);var i=t.resolve(e);if(!i)throw new Error("Failed to resolve module "+e);var r={id:e,require:t,filename:e,exports:{},loaded:!1,parent:null,children:[]},o=e.slice(0,e.lastIndexOf("/")+1);return t.cache[e]=r.exports,i.call(r.exports,r,r.exports,o,e),r.loaded=!0,t.cache[e]=r.exports}t.modules={},t.cache={},t.resolve=function(e){return{}.hasOwnProperty.call(t.modules,e)?t.modules[e]:void 0},t.define=function(e,n){t.modules[e]=n},t.define("little-emitter/emitter",function(e,t,n,i){!function(n,i){"function"==typeof define&&define.amd?define(i):"object"==typeof t?e.exports=i():i(n)}(this,function(e){"use strict";function t(e){return e?(e._events={},n(e,r)):void(this._events={})}function n(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e}function i(e){var t=[];for(var n in e)e.hasOwnProperty(n)&&(t=t.concat(e[n]));return t}var r,o=Array.prototype.slice;return r=t.prototype,r.on=r.addEventListener=function(e,t){return(this._events[e]=this._events[e]||[]).push(t),this},r.one=r.once=function(e,t){var n=function(){this.off(e,n),t.apply(this,arguments)};return n.fn=t,this.on(e,n)},r.off=r.removeAllListners=r.removeEventListener=function(e,t){var n=this._events[e];if(0===arguments.length)this._events={};else if(1===arguments.length)delete this._events[e];else if(n){for(var i,r=0;r<n.length;r++)if(i=n[r],i===t||i.fn===t){n.splice(r,1);break}n.length||delete this._events[e]}return this},r.emit=r.trigger=function(e){var t=this._events[e];if(!t)return!1;for(var n=0,i=t.length;i>n;n++)t[n].apply(this,o.call(arguments,1));return!0},r.listeners=function(e){return e?this._events[e]?this._events[e]:[]:i(this._events)},e?void(e.Emitter=t):t})}),t.define("./index",function(e,n,i,r){var o,s;o=t("little-emitter/emitter"),s={InitScript:"init-inform-script",InitForm:"init-inform-form",InitInputs:"init-inform-inputs",InitSubmits:"init-inform-submits",OnSubmit:"inform-submit",OnDone:"inform-done"},function(){var e,t,n,i,r,u;return e=new o,e.Events=s,i=function(e){var t,n;return n=document.getElementsByTagName(e),t=n[n.length-1]},u=i("script"),n=i("form"),t=!0,r=function(){var i,r,o,a,c,f,l,d,m,v,h,p,g,w,b;if(t){for(t=!1,e.emit(s.InitScript,u),e.emit(s.InitForm,n),w=[],c=[],f=n.getElementsByTagName("input"),o=0,m=f.length;m>o;o++)a=f[o],"submit"!==a.getAttribute("type")?c.push(a):w.push(a);for(f=n.getElementsByTagName("select"),l=0,v=f.length;v>l;l++)a=f[l],c.push(a);for(e.emit(s.InitInputs,c),r=n.getElementsByTagName("button"),d=0,h=r.length;h>d;d++)i=r[d],b=i.getAttribute("type"),(null==b||"submit"===b)&&w.push(i);return e.emit(s.InitSubmits,w),p=function(){return e.emit(s.OnDone)},g=function(t){var i;return i=function(){return n.removeEventListener("submit",g),n.addEventListener("submit",p),n.dispatchEvent(new Event("submit",{bubbles:!1,cancelable:!0}))},e.emit(s.OnSubmit,i,t),t.preventDefault()},n.addEventListener("submit",g)}},document.addEventListener?document.addEventListener("DOMContentLoaded",r,!1):document.attachEvent&&document.attachEvent("onreadystatechange",function(){return"complete"===document.readyState?r():void 0}),"undefined"!=typeof window&&null!==window&&(window.Inform=e,window.Inform.events=s,window.addEventListener?window.addEventListener("load",r,!1):window.attachEvent&&window.attachEvent("onload",r)),e}()}),t("./index")}).call(this,this);
|
||||
+5
-1
@@ -11,6 +11,7 @@
|
||||
"connect": "^3.4.0",
|
||||
"executive": "^0.4.8",
|
||||
"mocha": "^2.2.5",
|
||||
"phantomjs": "^1.9.17",
|
||||
"requisite": "^1.9.16",
|
||||
"selenium-standalone": "^4.5.3",
|
||||
"serve-static": "^1.10.0",
|
||||
@@ -37,5 +38,8 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/crowdstart/inform/issues"
|
||||
},
|
||||
"homepage": "https://github.com/crowdstart/inform#readme"
|
||||
"homepage": "https://github.com/crowdstart/inform#readme",
|
||||
"dependencies": {
|
||||
"little-emitter": "^0.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
+401
-303
@@ -1,324 +1,82 @@
|
||||
Emitter = require 'little-emitter'
|
||||
|
||||
events =
|
||||
InitScript: 'init-inform-script'
|
||||
InitForm: 'init-inform-form'
|
||||
InitInputs: 'init-inform-inputs'
|
||||
InitSubmits: 'init-inform-submits'
|
||||
OnSubmit: 'inform-submit'
|
||||
OnDone: 'inform-done'
|
||||
|
||||
do ->
|
||||
`var endpoint = "%s", ml = %s`
|
||||
|
||||
called = false
|
||||
errors = null
|
||||
forms = null
|
||||
handlers = null
|
||||
parent = null
|
||||
script = null
|
||||
selectors = {}
|
||||
validate = false
|
||||
|
||||
XHR = ->
|
||||
xhr = null
|
||||
|
||||
if window.XMLHttpRequest
|
||||
xhr = new XMLHttpRequest()
|
||||
|
||||
else if window.ActiveXObject
|
||||
xhr = new ActiveXObject 'Microsoft.XMLHTTP'
|
||||
|
||||
setHeaders: (headers) ->
|
||||
for k,v of headers
|
||||
xhr.setRequestHeader k, v
|
||||
return
|
||||
|
||||
post: (url, headers, payload, cb) ->
|
||||
xhr.open 'POST', url, true
|
||||
@setHeaders headers
|
||||
xhr.send payload
|
||||
|
||||
xhr.onreadystatechange = ->
|
||||
if xhr.readyState == 4
|
||||
if xhr.status == 200 or xhr.status == 201
|
||||
cb null, xhr.status, xhr
|
||||
else
|
||||
cb (new Error 'Subscription failed'), xhr.status, xhr
|
||||
return
|
||||
return
|
||||
|
||||
# get form container
|
||||
getContainer = (script, selector = '')->
|
||||
if selector != ''
|
||||
document.querySelector selectors.container
|
||||
else
|
||||
parent = script.parentNode
|
||||
inputs = parent.getElementsByTagName 'input'
|
||||
if inputs.length < 1
|
||||
document.body
|
||||
else
|
||||
parent
|
||||
emitter = new Emitter
|
||||
emitter.Events = events
|
||||
|
||||
# get this script tag
|
||||
getScript = ->
|
||||
getLastTag = (selector)->
|
||||
# find last script node
|
||||
scripts = document.getElementsByTagName( 'script' )
|
||||
tags = document.getElementsByTagName selector
|
||||
|
||||
# last element is this script tag
|
||||
script = scripts[ scripts.length - 1 ]
|
||||
script
|
||||
# last element is this tag
|
||||
tag = tags[tags.length - 1]
|
||||
return tag
|
||||
|
||||
# Get elements from inside a parent
|
||||
getElements = (parent, selector) ->
|
||||
console.log 'getElements', parent, selector
|
||||
script = getLastTag 'script'
|
||||
form = getLastTag 'form'
|
||||
|
||||
if selector? and selector != ''
|
||||
parent.querySelectorAll selector
|
||||
first = true
|
||||
init = ()->
|
||||
if first
|
||||
first = false
|
||||
else
|
||||
[parent]
|
||||
|
||||
# get value from a selector
|
||||
getValue = (parent = document.body, selector) ->
|
||||
el = parent.querySelector selector
|
||||
el?.value?.trim()
|
||||
|
||||
# serialize a form
|
||||
serializeForm = (el) ->
|
||||
return {} unless el?
|
||||
|
||||
data =
|
||||
metadata: {}
|
||||
|
||||
inputs = el.getElementsByTagName 'input'
|
||||
|
||||
# Loop over form elements
|
||||
for input in inputs
|
||||
# Clean up inputs
|
||||
k = input.name.trim().toLowerCase()
|
||||
v = input.value.trim()
|
||||
|
||||
# Skip inputs we don't care about
|
||||
if k == '' or v == '' or (input.getAttribute 'type') == 'submit'
|
||||
continue
|
||||
|
||||
# Detect emails
|
||||
if /email/.test k
|
||||
data.email = v
|
||||
else
|
||||
data.metadata[k] = v
|
||||
|
||||
# Use selectors if necessary
|
||||
if selectors.email
|
||||
data.email = getValue el, selectors.email
|
||||
else
|
||||
data.email ?= ''
|
||||
|
||||
for prop in ['firstname', 'lastname', 'name']
|
||||
if (selector = selectors[prop])?
|
||||
data.metadata[prop] = getValue el, selector
|
||||
|
||||
console.error 'Email is required' if data.email == ''
|
||||
|
||||
data
|
||||
|
||||
# get setting off script tag data attribute
|
||||
attr = (name) ->
|
||||
val = script.getAttribute 'data-' + name
|
||||
return unless val?
|
||||
|
||||
switch val.trim().toLowerCase()
|
||||
when 'false'
|
||||
false
|
||||
when 'true'
|
||||
true
|
||||
else
|
||||
val
|
||||
|
||||
# Google event tracking code
|
||||
google =
|
||||
setup: ->
|
||||
return if window.ga? or window._gaq?
|
||||
|
||||
((i, s, o, g, r, a, m) ->
|
||||
i['GoogleAnalyticsObject'] = r
|
||||
i[r] = i[r] or ->
|
||||
(i[r].q = i[r].q or []).push arguments
|
||||
return
|
||||
|
||||
i[r].l = 1 * new Date()
|
||||
|
||||
a = s.createElement(o)
|
||||
m = s.getElementsByTagName(o)[0]
|
||||
|
||||
a.async = 1
|
||||
a.src = g
|
||||
m.parentNode.insertBefore a, m
|
||||
return
|
||||
) window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'
|
||||
return
|
||||
|
||||
track: (opts) ->
|
||||
return unless opts.category?
|
||||
# you need to get the attributes off these things manually
|
||||
emitter.emit events.InitScript, script
|
||||
emitter.emit events.InitForm, form
|
||||
|
||||
google.setup()
|
||||
|
||||
category = opts.category ? 'Subscription'
|
||||
action = opts.action ? opts.name ? 'Signup'
|
||||
label = opts.label ? 'Lead'
|
||||
value = opts.value ? 1
|
||||
|
||||
if window._gaq?
|
||||
window._gaq.push ['_trackEvent', category, action, label, value]
|
||||
if window.ga?
|
||||
window.ga 'send', 'event', category, action, label, value
|
||||
return
|
||||
|
||||
# Facebook event tracking
|
||||
facebook =
|
||||
setup: ->
|
||||
return if window._fbq?.loaded
|
||||
|
||||
_fbq = window._fbq or (window._fbq = [])
|
||||
|
||||
fbds = document.createElement('script')
|
||||
fbds.async = true
|
||||
fbds.src = '//connect.facebook.net/en_US/fbds.js'
|
||||
s = document.getElementsByTagName('script')[0]
|
||||
s.parentNode.insertBefore fbds, s
|
||||
_fbq.loaded = true
|
||||
return
|
||||
|
||||
track: (opts) ->
|
||||
return unless opts.id?
|
||||
|
||||
facebook.setup()
|
||||
|
||||
value = opts.value ? '1.00'
|
||||
currency = opts.currency ? 'USD'
|
||||
|
||||
window._fbq.push ['track', opts.id,
|
||||
value: value,
|
||||
currency: currency,
|
||||
]
|
||||
return
|
||||
|
||||
# Trigger event tracking
|
||||
track = ->
|
||||
facebook.track ml.facebook
|
||||
google.track ml.google
|
||||
return
|
||||
|
||||
# Wire up submit handler
|
||||
addHandler = (el, errorEl) ->
|
||||
unless errorEl?
|
||||
errorEl = document.createElement 'div'
|
||||
errorEl.className = 'crowdstart-mailinglist-error'
|
||||
errorEl.style.display = 'none'
|
||||
errorEl.style.width = 100 + '%%'[0] # Prevents interpolation from picking up % as a thing needing interpolatin'
|
||||
el.appendChild errorEl
|
||||
|
||||
showError = (msg) ->
|
||||
errorEl.style.display = 'inline'
|
||||
errorEl.innerHTML = msg
|
||||
false
|
||||
|
||||
hideError = ->
|
||||
errorEl.style.display = 'none'
|
||||
|
||||
thankYou = ->
|
||||
switch ml.thankyou.type
|
||||
when 'redirect'
|
||||
setTimeout ->
|
||||
window.location = ml.thankyou.url
|
||||
, 1000
|
||||
when 'html'
|
||||
el.innerHTML = ml.thankyou.html
|
||||
|
||||
if document.createEvent && document.dispatchEvent
|
||||
event = document.createEvent 'Event'
|
||||
event.initEvent 'thankyou', true, true
|
||||
document.dispatchEvent event
|
||||
submits = []
|
||||
inputs = []
|
||||
ins = form.getElementsByTagName 'input'
|
||||
for input in ins
|
||||
if input.getAttribute('type') != 'submit'
|
||||
inputs.push input
|
||||
else
|
||||
console.log "Could not create or dispatch thankyou event"
|
||||
submits.push input
|
||||
|
||||
submitHandler = (ev) ->
|
||||
if ev.defaultPrevented
|
||||
return
|
||||
else
|
||||
ev.preventDefault()
|
||||
ins = form.getElementsByTagName 'select'
|
||||
for input in ins
|
||||
inputs.push input
|
||||
|
||||
data = serializeForm el
|
||||
console.log data
|
||||
emitter.emit events.InitInputs, inputs
|
||||
|
||||
if ml.validate
|
||||
unless data.email?
|
||||
return showError 'Email is required'
|
||||
if (data.email.indexOf '@') == -1
|
||||
return showError 'Invalid email'
|
||||
if data.email.length < 3
|
||||
return showError 'Invalid email'
|
||||
hideError()
|
||||
buttons = form.getElementsByTagName 'button'
|
||||
for button in buttons
|
||||
type = button.getAttribute('type')
|
||||
if !type? || type == 'submit'
|
||||
submits.push(button)
|
||||
|
||||
payload = JSON.stringify data
|
||||
emitter.emit events.InitSubmits, submits
|
||||
|
||||
headers =
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'Content-type': 'application/json; charset=utf-8'
|
||||
# Called on successful submit
|
||||
ondone = ()->
|
||||
emitter.emit events.OnDone
|
||||
|
||||
xhr = XHR()
|
||||
xhr.post endpoint, headers, payload, (err, status, xhr) ->
|
||||
return thankYou() if status == 409
|
||||
return showError(err) if err?
|
||||
# Called when trying to submit
|
||||
onsubmit = (event)->
|
||||
done = ()->
|
||||
form.removeEventListener 'submit', onsubmit
|
||||
form.addEventListener 'submit', ondone
|
||||
|
||||
# Fire tracking pixels
|
||||
track()
|
||||
thankYou()
|
||||
|
||||
false
|
||||
|
||||
(ev) ->
|
||||
el.removeEventListener 'submit', addHandler
|
||||
el.addEventListener 'submit', submitHandler
|
||||
|
||||
setTimeout ->
|
||||
el.dispatchEvent new Event 'submit',
|
||||
form.dispatchEvent new Event 'submit',
|
||||
bubbles: false
|
||||
cancelable: true
|
||||
, 500
|
||||
|
||||
ev.preventDefault()
|
||||
false
|
||||
# Call done to manually fire
|
||||
emitter.emit events.OnSubmit, done, event
|
||||
event.preventDefault()
|
||||
|
||||
# Init all the things
|
||||
init = ->
|
||||
if called then return else called = true
|
||||
|
||||
props = ['container', 'forms', 'submits', 'errors', 'email', 'firstname', 'lastname', 'name']
|
||||
for prop in props
|
||||
selectors[prop] = (attr prop) ? ml.selectors?[prop]
|
||||
|
||||
# default selector for submit button
|
||||
selectors.submits ?= 'input[type="submit"]'
|
||||
|
||||
# are we validating?
|
||||
ml.validate ?= (attr 'validate') ? false
|
||||
|
||||
parent = getContainer script, selectors.container
|
||||
forms = getElements parent, selectors.forms
|
||||
handlers = getElements parent, selectors.submits
|
||||
|
||||
# find error divs
|
||||
if selectors.errors
|
||||
errors = getElements parent, selectors.errors
|
||||
else
|
||||
errors = []
|
||||
|
||||
console.log 'selectors', selectors
|
||||
console.log 'forms', forms
|
||||
console.log 'handlers', handlers
|
||||
console.log 'errors', errors
|
||||
|
||||
for handler, i in handlers
|
||||
do (handler, i) ->
|
||||
return if handler.getAttribute 'data-hijacked'
|
||||
|
||||
handler.setAttribute 'data-hijacked', true
|
||||
handler.addEventListener 'click', (addHandler forms[i], errors[i])
|
||||
handler.addEventListener 'submit', (addHandler forms[i], errors[i])
|
||||
|
||||
# Get script tag, has to run before rest of DOM loads
|
||||
script = getScript()
|
||||
form.addEventListener 'submit', onsubmit
|
||||
|
||||
# Run init after DOM loads, attach various listeners
|
||||
if document.addEventListener
|
||||
@@ -327,9 +85,349 @@ do ->
|
||||
document.attachEvent 'onreadystatechange', ->
|
||||
init() if document.readyState == 'complete'
|
||||
|
||||
if window.addEventListener
|
||||
window.addEventListener 'load', init, false
|
||||
else if window.attachEvent
|
||||
window.attachEvent 'onload', init
|
||||
if window?
|
||||
window.Inform = emitter
|
||||
window.Inform.events = events
|
||||
|
||||
return
|
||||
if window.addEventListener
|
||||
window.addEventListener 'load', init, false
|
||||
else if window.attachEvent
|
||||
window.attachEvent 'onload', init
|
||||
|
||||
return emitter
|
||||
|
||||
# do ->
|
||||
# `var endpoint = "%s", ml = %s`
|
||||
|
||||
# called = false
|
||||
# errors = null
|
||||
# forms = null
|
||||
# handlers = null
|
||||
# parent = null
|
||||
# script = null
|
||||
# selectors = {}
|
||||
# validate = false
|
||||
|
||||
# XHR = ->
|
||||
# xhr = null
|
||||
|
||||
# if window.XMLHttpRequest
|
||||
# xhr = new XMLHttpRequest()
|
||||
|
||||
# else if window.ActiveXObject
|
||||
# xhr = new ActiveXObject 'Microsoft.XMLHTTP'
|
||||
|
||||
# setHeaders: (headers) ->
|
||||
# for k,v of headers
|
||||
# xhr.setRequestHeader k, v
|
||||
# return
|
||||
|
||||
# post: (url, headers, payload, cb) ->
|
||||
# xhr.open 'POST', url, true
|
||||
# @setHeaders headers
|
||||
# xhr.send payload
|
||||
|
||||
# xhr.onreadystatechange = ->
|
||||
# if xhr.readyState == 4
|
||||
# if xhr.status == 200 or xhr.status == 201
|
||||
# cb null, xhr.status, xhr
|
||||
# else
|
||||
# cb (new Error 'Subscription failed'), xhr.status, xhr
|
||||
# return
|
||||
# return
|
||||
|
||||
# # get form container
|
||||
# getContainer = (script, selector = '')->
|
||||
# if selector != ''
|
||||
# document.querySelector selectors.container
|
||||
# else
|
||||
# parent = script.parentNode
|
||||
# inputs = parent.getElementsByTagName 'input'
|
||||
# if inputs.length < 1
|
||||
# document.body
|
||||
# else
|
||||
# parent
|
||||
|
||||
# # get this script tag
|
||||
# getScript = ->
|
||||
# # find last script node
|
||||
# scripts = document.getElementsByTagName( 'script' )
|
||||
|
||||
# # last element is this script tag
|
||||
# script = scripts[ scripts.length - 1 ]
|
||||
# script
|
||||
|
||||
# # Get elements from inside a parent
|
||||
# getElements = (parent, selector) ->
|
||||
# console.log 'getElements', parent, selector
|
||||
|
||||
# if selector? and selector != ''
|
||||
# parent.querySelectorAll selector
|
||||
# else
|
||||
# [parent]
|
||||
|
||||
# # get value from a selector
|
||||
# getValue = (parent = document.body, selector) ->
|
||||
# el = parent.querySelector selector
|
||||
# el?.value?.trim()
|
||||
|
||||
# # serialize a form
|
||||
# serializeForm = (el) ->
|
||||
# return {} unless el?
|
||||
|
||||
# data =
|
||||
# metadata: {}
|
||||
|
||||
# inputs = el.getElementsByTagName 'input'
|
||||
|
||||
# # Loop over form elements
|
||||
# for input in inputs
|
||||
# # Clean up inputs
|
||||
# k = input.name.trim().toLowerCase()
|
||||
# v = input.value.trim()
|
||||
|
||||
# # Skip inputs we don't care about
|
||||
# if k == '' or v == '' or (input.getAttribute 'type') == 'submit'
|
||||
# continue
|
||||
|
||||
# # Detect emails
|
||||
# if /email/.test k
|
||||
# data.email = v
|
||||
# else
|
||||
# data.metadata[k] = v
|
||||
|
||||
# # Use selectors if necessary
|
||||
# if selectors.email
|
||||
# data.email = getValue el, selectors.email
|
||||
# else
|
||||
# data.email ?= ''
|
||||
|
||||
# for prop in ['firstname', 'lastname', 'name']
|
||||
# if (selector = selectors[prop])?
|
||||
# data.metadata[prop] = getValue el, selector
|
||||
|
||||
# console.error 'Email is required' if data.email == ''
|
||||
|
||||
# data
|
||||
|
||||
# # get setting off script tag data attribute
|
||||
# attr = (name) ->
|
||||
# val = script.getAttribute 'data-' + name
|
||||
# return unless val?
|
||||
|
||||
# switch val.trim().toLowerCase()
|
||||
# when 'false'
|
||||
# false
|
||||
# when 'true'
|
||||
# true
|
||||
# else
|
||||
# val
|
||||
|
||||
# # Google event tracking code
|
||||
# google =
|
||||
# setup: ->
|
||||
# return if window.ga? or window._gaq?
|
||||
|
||||
# ((i, s, o, g, r, a, m) ->
|
||||
# i['GoogleAnalyticsObject'] = r
|
||||
# i[r] = i[r] or ->
|
||||
# (i[r].q = i[r].q or []).push arguments
|
||||
# return
|
||||
|
||||
# i[r].l = 1 * new Date()
|
||||
|
||||
# a = s.createElement(o)
|
||||
# m = s.getElementsByTagName(o)[0]
|
||||
|
||||
# a.async = 1
|
||||
# a.src = g
|
||||
# m.parentNode.insertBefore a, m
|
||||
# return
|
||||
# ) window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'
|
||||
# return
|
||||
|
||||
# track: (opts) ->
|
||||
# return unless opts.category?
|
||||
|
||||
# google.setup()
|
||||
|
||||
# category = opts.category ? 'Subscription'
|
||||
# action = opts.action ? opts.name ? 'Signup'
|
||||
# label = opts.label ? 'Lead'
|
||||
# value = opts.value ? 1
|
||||
|
||||
# if window._gaq?
|
||||
# window._gaq.push ['_trackEvent', category, action, label, value]
|
||||
# if window.ga?
|
||||
# window.ga 'send', 'event', category, action, label, value
|
||||
# return
|
||||
|
||||
# # Facebook event tracking
|
||||
# facebook =
|
||||
# setup: ->
|
||||
# return if window._fbq?.loaded
|
||||
|
||||
# _fbq = window._fbq or (window._fbq = [])
|
||||
|
||||
# fbds = document.createElement('script')
|
||||
# fbds.async = true
|
||||
# fbds.src = '//connect.facebook.net/en_US/fbds.js'
|
||||
# s = document.getElementsByTagName('script')[0]
|
||||
# s.parentNode.insertBefore fbds, s
|
||||
# _fbq.loaded = true
|
||||
# return
|
||||
|
||||
# track: (opts) ->
|
||||
# return unless opts.id?
|
||||
|
||||
# facebook.setup()
|
||||
|
||||
# value = opts.value ? '1.00'
|
||||
# currency = opts.currency ? 'USD'
|
||||
|
||||
# window._fbq.push ['track', opts.id,
|
||||
# value: value,
|
||||
# currency: currency,
|
||||
# ]
|
||||
# return
|
||||
|
||||
# # Trigger event tracking
|
||||
# track = ->
|
||||
# facebook.track ml.facebook
|
||||
# google.track ml.google
|
||||
# return
|
||||
|
||||
# # Wire up submit handler
|
||||
# addHandler = (el, errorEl) ->
|
||||
# unless errorEl?
|
||||
# errorEl = document.createElement 'div'
|
||||
# errorEl.className = 'crowdstart-mailinglist-error'
|
||||
# errorEl.style.display = 'none'
|
||||
# errorEl.style.width = 100 + '%%'[0] # Prevents interpolation from picking up % as a thing needing interpolatin'
|
||||
# el.appendChild errorEl
|
||||
|
||||
# showError = (msg) ->
|
||||
# errorEl.style.display = 'inline'
|
||||
# errorEl.innerHTML = msg
|
||||
# false
|
||||
|
||||
# hideError = ->
|
||||
# errorEl.style.display = 'none'
|
||||
|
||||
# thankYou = ->
|
||||
# switch ml.thankyou.type
|
||||
# when 'redirect'
|
||||
# setTimeout ->
|
||||
# window.location = ml.thankyou.url
|
||||
# , 1000
|
||||
# when 'html'
|
||||
# el.innerHTML = ml.thankyou.html
|
||||
|
||||
# if document.createEvent && document.dispatchEvent
|
||||
# event = document.createEvent 'Event'
|
||||
# event.initEvent 'thankyou', true, true
|
||||
# document.dispatchEvent event
|
||||
# else
|
||||
# console.log "Could not create or dispatch thankyou event"
|
||||
|
||||
# submitHandler = (ev) ->
|
||||
# if ev.defaultPrevented
|
||||
# return
|
||||
# else
|
||||
# ev.preventDefault()
|
||||
|
||||
# data = serializeForm el
|
||||
# console.log data
|
||||
|
||||
# if ml.validate
|
||||
# unless data.email?
|
||||
# return showError 'Email is required'
|
||||
# if (data.email.indexOf '@') == -1
|
||||
# return showError 'Invalid email'
|
||||
# if data.email.length < 3
|
||||
# return showError 'Invalid email'
|
||||
# hideError()
|
||||
|
||||
# payload = JSON.stringify data
|
||||
|
||||
# headers =
|
||||
# 'X-Requested-With': 'XMLHttpRequest',
|
||||
# 'Content-type': 'application/json; charset=utf-8'
|
||||
|
||||
# xhr = XHR()
|
||||
# xhr.post endpoint, headers, payload, (err, status, xhr) ->
|
||||
# return thankYou() if status == 409
|
||||
# return showError(err) if err?
|
||||
|
||||
# # Fire tracking pixels
|
||||
# track()
|
||||
# thankYou()
|
||||
|
||||
# false
|
||||
|
||||
# (ev) ->
|
||||
# el.removeEventListener 'submit', addHandler
|
||||
# el.addEventListener 'submit', submitHandler
|
||||
|
||||
# setTimeout ->
|
||||
# el.dispatchEvent new Event 'submit',
|
||||
# bubbles: false
|
||||
# cancelable: true
|
||||
# , 500
|
||||
|
||||
# ev.preventDefault()
|
||||
# false
|
||||
|
||||
# # Init all the things
|
||||
# init = ->
|
||||
# if called then return else called = true
|
||||
|
||||
# props = ['container', 'forms', 'submits', 'errors', 'email', 'firstname', 'lastname', 'name']
|
||||
# for prop in props
|
||||
# selectors[prop] = (attr prop) ? ml.selectors?[prop]
|
||||
|
||||
# # default selector for submit button
|
||||
# selectors.submits ?= 'input[type="submit"]'
|
||||
|
||||
# # are we validating?
|
||||
# ml.validate ?= (attr 'validate') ? false
|
||||
|
||||
# parent = getContainer script, selectors.container
|
||||
# forms = getElements parent, selectors.forms
|
||||
# handlers = getElements parent, selectors.submits
|
||||
|
||||
# # find error divs
|
||||
# if selectors.errors
|
||||
# errors = getElements parent, selectors.errors
|
||||
# else
|
||||
# errors = []
|
||||
|
||||
# console.log 'selectors', selectors
|
||||
# console.log 'forms', forms
|
||||
# console.log 'handlers', handlers
|
||||
# console.log 'errors', errors
|
||||
|
||||
# for handler, i in handlers
|
||||
# do (handler, i) ->
|
||||
# return if handler.getAttribute 'data-hijacked'
|
||||
|
||||
# handler.setAttribute 'data-hijacked', true
|
||||
# handler.addEventListener 'click', (addHandler forms[i], errors[i])
|
||||
# handler.addEventListener 'submit', (addHandler forms[i], errors[i])
|
||||
|
||||
# # Get script tag, has to run before rest of DOM loads
|
||||
# script = getScript()
|
||||
|
||||
# # Run init after DOM loads, attach various listeners
|
||||
# if document.addEventListener
|
||||
# document.addEventListener 'DOMContentLoaded', init, false
|
||||
# else if document.attachEvent
|
||||
# document.attachEvent 'onreadystatechange', ->
|
||||
# init() if document.readyState == 'complete'
|
||||
|
||||
# if window.addEventListener
|
||||
# window.addEventListener 'load', init, false
|
||||
# else if window.attachEvent
|
||||
# window.attachEvent 'onload', init
|
||||
|
||||
# return
|
||||
|
||||
+18
-18
@@ -1,22 +1,22 @@
|
||||
module.exports = [
|
||||
browserName: 'iphone'
|
||||
platform: 'OS X 10.10'
|
||||
version: '8.2'
|
||||
deviceName: 'iPhone Simulator'
|
||||
deviceOrientation: 'portrait'
|
||||
,
|
||||
browserName: 'iphone'
|
||||
platform: 'OS X 10.10'
|
||||
version: '7.1'
|
||||
deviceName: 'iPhone Simulator'
|
||||
deviceOrientation: 'portrait'
|
||||
,
|
||||
browserName: 'iphone'
|
||||
platform: 'OS X 10.10'
|
||||
version: '6.1'
|
||||
deviceName: 'iPhone Simulator'
|
||||
deviceOrientation: 'portrait'
|
||||
,
|
||||
# browserName: 'iphone'
|
||||
# platform: 'OS X 10.10'
|
||||
# version: '8.2'
|
||||
# deviceName: 'iPhone Simulator'
|
||||
# deviceOrientation: 'portrait'
|
||||
# ,
|
||||
# browserName: 'iphone'
|
||||
# platform: 'OS X 10.10'
|
||||
# version: '7.1'
|
||||
# deviceName: 'iPhone Simulator'
|
||||
# deviceOrientation: 'portrait'
|
||||
# ,
|
||||
# browserName: 'iphone'
|
||||
# platform: 'OS X 10.10'
|
||||
# version: '6.1'
|
||||
# deviceName: 'iPhone Simulator'
|
||||
# deviceOrientation: 'portrait'
|
||||
# ,
|
||||
browserName: 'android'
|
||||
platform: 'Linux'
|
||||
version: '5.1'
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../inform.js
|
||||
Vendored
+5
File diff suppressed because one or more lines are too long
+62
-2
@@ -7,5 +7,65 @@ describe "Inform (#{process.env.BROWSER})", ->
|
||||
browser = getBrowser()
|
||||
testPage = "http://localhost:#{process.env.PORT ? 3333}/test.html"
|
||||
|
||||
it 'Should load', ->
|
||||
require '../src'
|
||||
it 'should detect the correct script/form', (done)->
|
||||
browser
|
||||
.url testPage
|
||||
.waitForExist "#lastthing"
|
||||
.getText '#script', (err, res) ->
|
||||
res.should.equal 'inform'
|
||||
.getText '#form', (err, res) ->
|
||||
res.should.equal 'test'
|
||||
.getText '#inputs', (err, res) ->
|
||||
res.should.equal 'email: testuser@email.com, name: Test User, misc: Something'
|
||||
.getText '#submits', (err, res) ->
|
||||
res.should.equal 's, as, aas'
|
||||
.call done
|
||||
|
||||
#dispatchEvent doesn't seem to work
|
||||
if process.env.BROWSER != 'phantomjs'
|
||||
it 'should submit and done for submit input', (done)->
|
||||
browser
|
||||
.url testPage
|
||||
.waitForExist "#lastthing"
|
||||
.click '#s'
|
||||
.getText '#submited', (err, res) ->
|
||||
res.should.equal 'true'
|
||||
.getText '#doned', (err, res) ->
|
||||
res.should.equal 'true'
|
||||
.call done
|
||||
|
||||
it 'should submit and done for untyped button', (done)->
|
||||
browser
|
||||
.url testPage
|
||||
.waitForExist "#lastthing"
|
||||
.click '#as'
|
||||
# yes we actually need this as there are delays in the code
|
||||
.getText '#submited', (err, res) ->
|
||||
res.should.equal 'true'
|
||||
.getText '#doned', (err, res) ->
|
||||
res.should.equal 'true'
|
||||
.call done
|
||||
|
||||
it 'should submit and done for submit button', (done)->
|
||||
browser
|
||||
.url testPage
|
||||
.waitForExist "#lastthing"
|
||||
.click '#aas'
|
||||
# yes we actually need this as there are delays in the code
|
||||
.getText '#submited', (err, res) ->
|
||||
res.should.equal 'true'
|
||||
.getText '#doned', (err, res) ->
|
||||
res.should.equal 'true'
|
||||
.call done
|
||||
|
||||
it 'should not submit or done for other button', (done)->
|
||||
browser
|
||||
.url testPage
|
||||
.waitForExist "#lastthing"
|
||||
.click '#r'
|
||||
# yes we actually need this as there are delays in the code
|
||||
.getText '#submited', (err, res) ->
|
||||
res.should.equal 'false'
|
||||
.getText '#doned', (err, res) ->
|
||||
res.should.equal 'false'
|
||||
.call done
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title></title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png">
|
||||
<script src="jquery-1.11.3.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<form id="wrongform">
|
||||
</form>
|
||||
<form id="test">
|
||||
<script id="inform" src="inform.js"></script>
|
||||
<input id="email" value="testuser@email.com"></input>
|
||||
<input id="name" value="Test User"></input>
|
||||
<input id="misc" value="Something"></input>
|
||||
<input id = "s" type="submit"></input>
|
||||
<button id="as">Also Submit</button>
|
||||
<button id="aas" type="submit">Also Also Submit</button>
|
||||
<button id="r" type="reset">Reset</button>
|
||||
</form>
|
||||
<form id="alsowrongform">
|
||||
</form>
|
||||
<div id="script">
|
||||
</div>
|
||||
<div id="form">
|
||||
</div>
|
||||
<div id="inputs">
|
||||
</div>
|
||||
<div id="submits">
|
||||
</div>
|
||||
<div id="submited">false</div>
|
||||
<div id="doned">false</div>
|
||||
|
||||
<script id="lastthing">
|
||||
var Inform = window.Inform
|
||||
|
||||
Inform.once(Inform.Events.InitScript, function(el){
|
||||
$('#script').html(el.id)
|
||||
})
|
||||
|
||||
Inform.once(Inform.Events.InitForm, function(el){
|
||||
$('#form').html(el.id)
|
||||
})
|
||||
|
||||
Inform.once(Inform.Events.InitInputs, function(els){
|
||||
$('#inputs').html(els.map(function(el){
|
||||
$el = $(el)
|
||||
return $el.attr('id') + ': ' + $el.val()
|
||||
}).join(', '))
|
||||
})
|
||||
|
||||
Inform.once(Inform.Events.InitSubmits, function(els){
|
||||
$('#submits').html(els.map(function(el){
|
||||
return el.id
|
||||
}).join(', '))
|
||||
})
|
||||
|
||||
Inform.once(Inform.Events.OnSubmit, function(done){
|
||||
$('#submited').html('true')
|
||||
done()
|
||||
})
|
||||
|
||||
Inform.once(Inform.Events.OnDone, function(){
|
||||
$('#doned').html('true')
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+4
-1
@@ -2,11 +2,14 @@ webdriver = require 'webdriverio'
|
||||
|
||||
exports.getBrowser = ->
|
||||
caps =
|
||||
browserName: process.env.BROWSER ? 'phantomjs'
|
||||
#dispatch event no worky in phantomjs
|
||||
browserName: 'chrome'
|
||||
platform: process.env.PLATFORM
|
||||
version: process.env.VERSION
|
||||
deviceName: process.env.DEVICE_NAME
|
||||
deviceOrientation: process.env.DEVICE_ORIENTATION
|
||||
'phantomjs.binary.path': './node_modules/phantomjs/bin/phantomjs'
|
||||
logLevel: 'verbose'
|
||||
|
||||
opts =
|
||||
desiredCapabilities: caps
|
||||
|
||||
Reference in New Issue
Block a user