1

I'm trying to automate the filling out of an AWS lambda function with selenium and python with the chrome driver; however, I'm unable to enter text into the ace editor.

The html for the editor looks like this:

 <div class="codeditorHolder ace_editor aceFocus ace-cloud9-day" style="position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; font-family: Monaco, Menlo, &quot;Ubuntu Mono&quot;, Consolas, source-code-pro, monospace;">
  <textarea class="ace_text-input" wrap="off" autocorrect="off" autocapitalize="off" spellcheck="false" style="opacity: 0; height: 14.4px; width: 6.59775px; left: 44px; top: 0px;"></textarea>
  <div class="ace_gutter ace_fade-fold-widgets">
    <div class="ace_layer ace_gutter-layer ace_folding-enabled" style="margin-top: 0px; height: 556.8px; width: 40px;">
      <div class="ace_gutter-cell " style="height: 14.4px;">1<span class="ace_fold-widget ace_start ace_open" style="height: 14.4px;"></span></div>
      <div class="ace_gutter-cell " style="height: 14.4px;">2</div>
      <div class="ace_gutter-cell " style="height: 14.4px;">3</div>
      <div class="ace_gutter-cell " style="height: 14.4px;">4</div>
    </div>
    <div class="ace_gutter-active-line" style="top: 0px; height: 14.4px;"></div>
  </div>
  <div class="ace_scroller" style="left: 40px; right: 0px; bottom: 0px;">
    <div class="ace_content" style="margin-top: 0px; width: 1023px; height: 556.8px; margin-left: 0px;">
      <div class="ace_layer ace_print-margin-layer">
        <div class="ace_print-margin" style="left: 531.82px; visibility: visible;"></div>
      </div>
      <div class="ace_layer ace_marker-layer">
        <div class="ace_active-line" style="height:14.40000057220459px;top:0px;left:0;right:0;"></div>
      </div>
      <div class="ace_layer ace_text-layer" style="padding: 0px 4px;">
        <div class="ace_line" style="height:14.40000057220459px"><span class="ace_keyword">def</span> <span class="ace_identifier">lambda_handler</span><span class="ace_paren ace_lparen">(</span><span class="ace_identifier">event</span>, <span class="ace_identifier">context</span><span class="ace_paren ace_rparen">)</span>:</div>
        <div class="ace_line" style="height:14.40000057220459px"> <span class="ace_comment"># TODO implement</span></div>
        <div class="ace_line" style="height:14.40000057220459px"> <span class="ace_keyword">return</span> <span class="ace_string">'Hello from Lambda'</span></div>
        <div class="ace_line" style="height:14.40000057220459px"></div>
      </div>
      <div class="ace_layer ace_marker-layer"></div>
      <div class="ace_layer ace_cursor-layer ace_hidden-cursors">
        <div class="ace_cursor" style="left: 4px; top: 0px; width: 6.59775px; height: 14.4px;"></div>
      </div>
    </div>
    <div class="scroll_shadow">
      <div class="ace_corner"></div>
    </div>
  </div>
  <div class="ace_scrollbar ace_scrollbar-v" style="display: none; width: 21px; bottom: 0px;">
    <div class="ace_scrollbar-inner" style="width: 21px; height: 528px;"></div>
  </div>
  <div class="ace_scrollbar ace_scrollbar-h" style="height: 21px; left: 40px; right: 0px; display: none;">
    <div class="ace_scrollbar-inner" style="height: 21px; width: 1023px;"></div>
  </div>
  <div style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; overflow: hidden;">
    <div style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; overflow: visible;"></div>
    <div style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; font-style: inherit; font-variant: inherit; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; overflow: visible;">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div>
  </div>
</div>

And if we remove everything that doesn't have to do with the content itself, then it looks like this:

<div class="codeditorHolder ace_editor aceFocus ace-cloud9-day" style="position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; font-family: Monaco, Menlo, &quot;Ubuntu Mono&quot;, Consolas, source-code-pro, monospace;">
  <textarea class="ace_text-input" wrap="off" autocorrect="off" autocapitalize="off" spellcheck="false" style="opacity: 0; height: 14.4px; width: 6.59775px; left: 44px; top: 0px;"></textarea>
  <div class="ace_scroller" style="left: 40px; right: 0px; bottom: 0px;">
    <div class="ace_content" style="margin-top: 0px; width: 1023px; height: 556.8px; margin-left: 0px;">
      <div class="ace_layer ace_print-margin-layer">
        <div class="ace_print-margin" style="left: 531.82px; visibility: visible;"></div>
      </div>
      <div class="ace_layer ace_marker-layer">
        <div class="ace_active-line" style="height:14.40000057220459px;top:0px;left:0;right:0;"></div>
      </div>
      <div class="ace_layer ace_text-layer" style="padding: 0px 4px;">
        <div class="ace_line" style="height:14.40000057220459px"><span class="ace_keyword">def</span> <span class="ace_identifier">lambda_handler</span><span class="ace_paren ace_lparen">(</span><span class="ace_identifier">event</span>, <span class="ace_identifier">context</span><span class="ace_paren ace_rparen">)</span>:</div>
        <div class="ace_line" style="height:14.40000057220459px"> <span class="ace_comment"># TODO implement</span></div>
        <div class="ace_line" style="height:14.40000057220459px"> <span class="ace_keyword">return</span> <span class="ace_string">'Hello from Lambda'</span></div>
        <div class="ace_line" style="height:14.40000057220459px"></div>
      </div>
      <div class="ace_layer ace_marker-layer"></div>
      <div class="ace_layer ace_cursor-layer ace_hidden-cursors">
        <div class="ace_cursor" style="left: 4px; top: 0px; width: 6.59775px; height: 14.4px;"></div>
      </div>
    </div>
    <div class="scroll_shadow">
      <div class="ace_corner"></div>
    </div>
</div>

The default code inside the editor is the following:

def lambda_handler(event, context):
    # TODO implement
    return 'Hello from Lambda'

I've tried sending keys to textarea element:

<textarea class="ace_text-input" wrap="off" autocorrect="off" autocapitalize="off" spellcheck="false" style="opacity: 0; height: 14.4px; width: 6.59775px; left: 44px; top: 0px;"></textarea> 

by using sendkeys:

driver.find_element_by_css_selector('textarea.ace_text-input').send_keys('code')

What do I need to do with in python and selenium in order to automate the ace text editor?

I've seen another thread on this topic, but its solutions didn't seem to work and it was nearly 2.5 years old.

Thanks.

dbryan
  • 153
  • 1
  • 2
  • 5

1 Answers1

3

First, answner your confuse: why change the value of the textarea, you not see any change happen?
Because the size of the textarea is too small to display the content inside it. you can verify this by select the textarea DOM node in DevTool Element Tab, and monitor the highlight element on page, you will noticed there is a very small box highlighted. Or you can change its style to increase width and height, then you can see your changed value on it.

Actual ACE Editor supply API: setValue() to set new content into the editor

1) Before you call this API, you need to find out the ACE Editor instance variable name on your page, you should try to find smilar code snippet as below from all javascript used by your page:

enter image description here

2) The var editor is what we wanted, now you can do a quick check to see you find the right variable by execute below code in DevTool's console Tab:

editor.setValue('function test(){}') //remeber replace the editor to yours name.

If the content in editor changed, you get the correct one.

For more detail please go to https://ace.c9.io/#nav=embedding

3) The last step to call selenium python API: execute_script() to execute a javascript snippet in your automation to change the editor content:

editor_variable_name = '' 
new_content = ''
script = 'arguments[0].setValue(arguments[1])'
driver.execute_script(script, editor_variable_name, new_content);

Note: We need the ACE Editor instance is a global variable, means you can access it by pattern: windows.xxxx, If it's decleared inside a javascript closure, there is no way to access it outside closure. If you can succeed at Step 2), means it's a global variable.

yong
  • 13,357
  • 1
  • 16
  • 27
  • note, if the result ace.edit(element) is not stored globally, it is still possible to access it using element,env.editor – a user Jan 06 '18 at 08:54
  • I not heard env.editor, so i don't know it can or not. If the ace editor instance is not stored globally, i don't know there is other way. I begin to learn the ACE Editor when I attempt to answer your question, but i think if someone learn ACE Editor deeply, maybe he know the other way. – yong Jan 06 '18 at 12:02
  • 2
    It worked me just finding the id of the editor, waiting for it to be present and then driver.execute_script('ace.edit("editor-id").setValue("some value")') – avriis Sep 05 '18 at 12:24