lib/capybara/poltergeist/client/agent.coffee in poltergeist-1.7.0 vs lib/capybara/poltergeist/client/agent.coffee in poltergeist-1.8.0

- old
+ new

@@ -1,8 +1,12 @@ # This is injected into each page that is loaded class PoltergeistAgent + # Since this code executes in the sites browser space - copy needed JSON functions + # in case user code messes with JSON (early mootools for instance) + @.JSON ||= { parse: JSON.parse, stringify: JSON.stringify } + constructor: -> @elements = [] @nodes = {} externalCall: (name, args) -> @@ -11,11 +15,11 @@ catch error { error: { message: error.toString(), stack: error.stack } } @stringify: (object) -> try - JSON.stringify object, (key, value) -> + PoltergeistAgent.JSON.stringify object, (key, value) -> if Array.isArray(this[key]) return this[key] else return value catch error @@ -118,10 +122,12 @@ # In the case of an OPTION tag, the change event should come # from the parent SELECT if @element.nodeName == 'OPTION' element = @element.parentNode + element = element.parentNode if element.nodeName == 'OPTGROUP' + element else element = @element element.dispatchEvent(event) @@ -170,13 +176,16 @@ range.selectNodeContents(@element) window.getSelection().removeAllRanges() window.getSelection().addRange(range) window.getSelection().deleteFromDocument() + getProperty: (name) -> + @element[name] + getAttributes: -> attrs = {} - for attr, i in @element.attributes + for attr in @element.attributes attrs[attr.name] = attr.value.replace("\n","\\n"); attrs getAttribute: (name) -> if name == 'checked' || name == 'selected' @@ -184,10 +193,14 @@ else @element.getAttribute(name) scrollIntoView: -> @element.scrollIntoViewIfNeeded() + #Sometimes scrollIntoViewIfNeeded doesn't seem to work, not really sure why. + #Just calling scrollIntoView doesnt work either, however calling scrollIntoView + #after scrollIntoViewIfNeeded when element is not in the viewport does appear to work + @element.scrollIntoView() unless this.isInViewport() value: -> if @element.tagName == 'SELECT' && @element.multiple option.value for option in @element.children when option.selected else @@ -197,12 +210,12 @@ return if @element.readOnly if (@element.maxLength >= 0) value = value.substr(0, @element.maxLength) - @element.value = '' this.trigger('focus') + @element.value = '' if @element.type == 'number' @element.value = value else for char in value @@ -242,19 +255,29 @@ tagName: -> @element.tagName isVisible: (element) -> - element = @element unless element + element ||= @element - if window.getComputedStyle(element).display == 'none' - false - else if element.parentElement - this.isVisible element.parentElement - else - true + while (element) + style = window.getComputedStyle(element) + return false if style.display == 'none' or + style.visibility == 'hidden' or + parseFloat(style.opacity) == 0 + element = element.parentElement + return true + + isInViewport: -> + rect = @element.getBoundingClientRect(); + + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= window.innerHeight && + rect.right <= window.innerWidth + isDisabled: -> @element.disabled || @element.tagName == 'OPTION' && @element.parentNode.disabled path: -> elements = @parentIds().reverse().map((id) => @agent.get(id)) @@ -338,15 +361,17 @@ return { status: 'success' } else el = el.parentNode { status: 'failure', selector: origEl && this.getSelector(origEl) } - getSelector: (el) -> selector = if el.tagName != 'HTML' then this.getSelector(el.parentNode) + ' ' else '' selector += el.tagName.toLowerCase() selector += "##{el.id}" if el.id - for className in el.classList + + #PhantomJS < 2.0 doesn't support classList for SVG elements - so get classes manually + classes = el.classList || (el.getAttribute('class')?.trim()?.split(/\s+/)) || [] + for className in classes when className != '' selector += ".#{className}" selector characterToKeyCode: (character) -> code = character.toUpperCase().charCodeAt(0)