chore: dropped legacy selenium dependant tests
selenium TestDriver deprecated --ui-tests flag in `bench run-tests` deprecated
This commit is contained in:
parent
cbd89842ee
commit
ae48dfe2b4
24 changed files with 3 additions and 1348 deletions
|
|
@ -507,26 +507,6 @@ def run_ui_tests(context, app, headless=False):
|
|||
formatted_command = command.format(site_env=site_env, password_env=password_env, run_or_open=run_or_open)
|
||||
frappe.commands.popen(formatted_command, cwd=app_base_path, raise_err=True)
|
||||
|
||||
@click.command('run-setup-wizard-ui-test')
|
||||
@click.option('--app', help="App to run tests on, leave blank for all apps")
|
||||
@click.option('--profile', is_flag=True, default=False)
|
||||
@pass_context
|
||||
def run_setup_wizard_ui_test(context, app=None, profile=False):
|
||||
"Run setup wizard UI test"
|
||||
import frappe.test_runner
|
||||
|
||||
site = get_site(context)
|
||||
frappe.init(site=site)
|
||||
frappe.connect()
|
||||
|
||||
ret = frappe.test_runner.run_setup_wizard_ui_test(app=app, verbose=context.verbose,
|
||||
profile=profile)
|
||||
if len(ret.failures) == 0 and len(ret.errors) == 0:
|
||||
ret = 0
|
||||
|
||||
if os.environ.get('CI'):
|
||||
sys.exit(ret)
|
||||
|
||||
@click.command('serve')
|
||||
@click.option('--port', default=8000)
|
||||
@click.option('--profile', is_flag=True, default=False)
|
||||
|
|
@ -752,7 +732,6 @@ commands = [
|
|||
reset_perms,
|
||||
run_tests,
|
||||
run_ui_tests,
|
||||
run_setup_wizard_ui_test,
|
||||
serve,
|
||||
set_config,
|
||||
show_config,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ def main(app=None, module=None, doctype=None, verbose=False, tests=(),
|
|||
with open(frappe.get_app_path(app, doctype_list_path), 'r') as f:
|
||||
doctype = f.read().strip().splitlines()
|
||||
|
||||
if ui_tests:
|
||||
print("Selenium testing has been deprecated\nUse bench --site {site_name} run-ui-tests for Cypress tests")
|
||||
|
||||
xmloutput_fh = None
|
||||
if junit_xml_output:
|
||||
xmloutput_fh = open(junit_xml_output, 'w')
|
||||
|
|
@ -170,21 +173,6 @@ def run_tests_for_module(module, verbose=False, tests=(), profile=False):
|
|||
|
||||
return _run_unittest(module, verbose=verbose, tests=tests, profile=profile)
|
||||
|
||||
def run_setup_wizard_ui_test(app=None, verbose=False, profile=False):
|
||||
'''Run setup wizard UI test using test_test_runner'''
|
||||
frappe.flags.run_setup_wizard_ui_test = 1
|
||||
return run_ui_tests(app=app, test=None, verbose=verbose, profile=profile)
|
||||
|
||||
def run_ui_tests(app=None, test=None, test_list=None, verbose=False, profile=False):
|
||||
'''Run a single unit test for UI using test_test_runner'''
|
||||
module = importlib.import_module('frappe.tests.ui.test_test_runner')
|
||||
frappe.flags.ui_test_app = app
|
||||
if test_list:
|
||||
frappe.flags.ui_test_list = test_list
|
||||
else:
|
||||
frappe.flags.ui_test_path = test
|
||||
return _run_unittest(module, verbose=verbose, tests=(), profile=profile)
|
||||
|
||||
def _run_unittest(modules, verbose=False, tests=(), profile=False):
|
||||
test_suite = unittest.TestSuite()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,85 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest, frappe, requests, time
|
||||
from frappe.test_runner import make_test_records
|
||||
from frappe.utils.selenium_testdriver import TestDriver
|
||||
from six.moves.urllib.parse import urlparse
|
||||
from frappe.frappeclient import FrappeOAuth2Client
|
||||
|
||||
class TestFrappeOAuth2Client(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.driver = TestDriver()
|
||||
make_test_records("OAuth Client")
|
||||
make_test_records("User")
|
||||
self.client_id = frappe.get_all("OAuth Client", fields=["*"])[0].get("client_id")
|
||||
|
||||
# Set Frappe server URL reqired for id_token generation
|
||||
try:
|
||||
frappe_login_key = frappe.get_doc("Social Login Key", "frappe")
|
||||
except frappe.DoesNotExistError:
|
||||
frappe_login_key = frappe.new_doc("Social Login Key")
|
||||
frappe_login_key.get_social_login_provider("Frappe", initialize=True)
|
||||
frappe_login_key.base_url = "http://localhost:8000"
|
||||
frappe_login_key.save()
|
||||
|
||||
def test_insert_note(self):
|
||||
|
||||
# Go to Authorize url
|
||||
self.driver.get(
|
||||
"api/method/frappe.integrations.oauth2.authorize?client_id=" +
|
||||
self.client_id +
|
||||
"&scope=all%20openid&response_type=code&redirect_uri=http%3A%2F%2Flocalhost"
|
||||
)
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# Login
|
||||
username = self.driver.find("#login_email")[0]
|
||||
username.send_keys("test@example.com")
|
||||
|
||||
password = self.driver.find("#login_password")[0]
|
||||
password.send_keys("Eastern_43A1W")
|
||||
|
||||
sign_in = self.driver.find(".btn-login")[0]
|
||||
sign_in.submit()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# Allow access to resource
|
||||
allow = self.driver.find("#allow")[0]
|
||||
allow.click()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# Get authorization code from redirected URL
|
||||
auth_code = urlparse(self.driver.driver.current_url).query.split("=")[1]
|
||||
|
||||
payload = "grant_type=authorization_code&code="
|
||||
payload += auth_code
|
||||
payload += "&redirect_uri=http%3A%2F%2Flocalhost&client_id="
|
||||
payload += self.client_id
|
||||
|
||||
headers = {'content-type':'application/x-www-form-urlencoded'}
|
||||
|
||||
# Request for bearer token
|
||||
token_response = requests.post( frappe.get_site_config().host_name +
|
||||
"/api/method/frappe.integrations.oauth2.get_token", data=payload, headers=headers)
|
||||
|
||||
# Parse bearer token json
|
||||
bearer_token = token_response.json()
|
||||
client = FrappeOAuth2Client(frappe.get_site_config().host_name, bearer_token.get("access_token"))
|
||||
|
||||
notes = [
|
||||
{"doctype": "Note", "title": "Sing", "public": True},
|
||||
{"doctype": "Note", "title": "a", "public": True},
|
||||
{"doctype": "Note", "title": "Song", "public": True},
|
||||
{"doctype": "Note", "title": "of", "public": True},
|
||||
{"doctype": "Note", "title": "sixpence", "public": True}
|
||||
]
|
||||
|
||||
for note in notes:
|
||||
client.insert(note)
|
||||
|
||||
self.assertTrue(len(frappe.get_all("Note")) == 5)
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
frappe.tests = {
|
||||
data: {},
|
||||
make: function(doctype, data) {
|
||||
let dialog_is_active = () => {
|
||||
return (
|
||||
cur_dialog && (!cur_frm || cur_frm.doc.doctype != doctype)
|
||||
);
|
||||
};
|
||||
return frappe.run_serially([
|
||||
() => frappe.set_route('List', doctype),
|
||||
() => frappe.new_doc(doctype),
|
||||
() => {
|
||||
if (frappe.quick_entry) {
|
||||
frappe.quick_entry.dialog.$wrapper.find('.edit-full').click();
|
||||
return frappe.timeout(1);
|
||||
} else {
|
||||
let root_node;
|
||||
if (cur_tree) {
|
||||
for (const key in cur_tree.nodes) {
|
||||
if (cur_tree.nodes[key].parent_label && cur_tree.nodes[key].expandable) {
|
||||
root_node = cur_tree.nodes[key].label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (root_node){
|
||||
frappe.tests.open_add_child_dialog(root_node);
|
||||
return frappe.timeout(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
() => {
|
||||
if(dialog_is_active()) {
|
||||
return frappe.tests.set_dialog_values(cur_dialog, data);
|
||||
} else {
|
||||
return frappe.tests.set_form_values(cur_frm, data);
|
||||
}
|
||||
},
|
||||
|
||||
() => {
|
||||
if(dialog_is_active()) {
|
||||
return cur_dialog.get_primary_btn().click();
|
||||
} else {
|
||||
return frappe.quick_entry ? frappe.quick_entry.insert() : cur_frm.save();
|
||||
}
|
||||
}
|
||||
]);
|
||||
},
|
||||
open_add_child_dialog: (root_node) => {
|
||||
frappe.tests.click_link(root_node);
|
||||
frappe.timeout(1);
|
||||
frappe.tests.click_button('Add Child');
|
||||
},
|
||||
set_form_values: (frm, data) => {
|
||||
let tasks = [];
|
||||
|
||||
data.forEach(item => {
|
||||
for (let key in item) {
|
||||
let task = () => {
|
||||
let value = item[key];
|
||||
if ($.isArray(value)) {
|
||||
return frappe.tests.set_grid_values(frm, key, value);
|
||||
} else {
|
||||
// single value
|
||||
return frm.set_value(key, value);
|
||||
}
|
||||
};
|
||||
tasks.push(task);
|
||||
tasks.push(frappe.after_ajax);
|
||||
tasks.push(() => frappe.timeout(0.4));
|
||||
}
|
||||
});
|
||||
|
||||
// set values
|
||||
return frappe.run_serially(tasks);
|
||||
|
||||
},
|
||||
set_dialog_values: (dialog, data) => {
|
||||
let tasks = [];
|
||||
|
||||
data.forEach(item => {
|
||||
for (let key in item) {
|
||||
let task = () => {
|
||||
let value = item[key];
|
||||
return dialog.set_value(key, value);
|
||||
};
|
||||
tasks.push(task);
|
||||
tasks.push(frappe.after_ajax);
|
||||
tasks.push(() => frappe.timeout(0.4));
|
||||
}
|
||||
});
|
||||
|
||||
return frappe.run_serially(tasks);
|
||||
},
|
||||
set_grid_values: (frm, key, value) => {
|
||||
// set value in grid
|
||||
let grid = frm.get_field(key).grid;
|
||||
grid.remove_all();
|
||||
|
||||
let grid_row_tasks = [];
|
||||
|
||||
// build tasks for each row
|
||||
value.forEach(d => {
|
||||
grid_row_tasks.push(() => {
|
||||
|
||||
let grid_value_tasks = [];
|
||||
grid_value_tasks.push(() => grid.add_new_row());
|
||||
grid_value_tasks.push(() => grid.get_row(-1).toggle_view(true));
|
||||
grid_value_tasks.push(() => frappe.timeout(0.5));
|
||||
|
||||
// build tasks to set each row value
|
||||
d.forEach(child_value => {
|
||||
for (let child_key in child_value) {
|
||||
grid_value_tasks.push(() => {
|
||||
let grid_row = grid.get_row(-1);
|
||||
return frappe.model.set_value(grid_row.doc.doctype,
|
||||
grid_row.doc.name, child_key, child_value[child_key]);
|
||||
});
|
||||
grid_value_tasks.push(frappe.after_ajax);
|
||||
grid_value_tasks.push(() => frappe.timeout(0.4));
|
||||
}
|
||||
});
|
||||
|
||||
return frappe.run_serially(grid_value_tasks);
|
||||
});
|
||||
});
|
||||
return frappe.run_serially(grid_row_tasks);
|
||||
},
|
||||
setup_doctype: (doctype, data) => {
|
||||
return frappe.run_serially([
|
||||
() => frappe.set_route('List', doctype),
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
frappe.tests.data[doctype] = [];
|
||||
let expected = Object.keys(data);
|
||||
cur_list.data.forEach((d) => {
|
||||
frappe.tests.data[doctype].push(d.name);
|
||||
if(expected.indexOf(d.name) !== -1) {
|
||||
expected[expected.indexOf(d.name)] = null;
|
||||
}
|
||||
});
|
||||
|
||||
let tasks = [];
|
||||
|
||||
expected.forEach(function(d) {
|
||||
if(d) {
|
||||
tasks.push(() => frappe.tests.make(doctype,
|
||||
data[d]));
|
||||
}
|
||||
});
|
||||
|
||||
return frappe.run_serially(tasks);
|
||||
}]);
|
||||
},
|
||||
click_page_head_item: (text) => {
|
||||
// Method to items present on the page header like New, Save, Delete etc.
|
||||
let possible_texts = ["New", "Delete", "Save", "Yes"];
|
||||
return frappe.run_serially([
|
||||
() => {
|
||||
if (text == "Menu"){
|
||||
$(`span.menu-btn-group-label:contains('Menu'):visible`).click();
|
||||
} else if (text == "Refresh") {
|
||||
$(`.btn-secondary:contains('Refresh'):visible`).click();
|
||||
} else if (possible_texts.includes(text)) {
|
||||
$(`.btn-primary:contains("${text}"):visible`).click();
|
||||
}
|
||||
},
|
||||
() => frappe.timeout(1)
|
||||
]);
|
||||
},
|
||||
click_dropdown_item: (text) => {
|
||||
// Method to click dropdown elements
|
||||
return frappe.run_serially([
|
||||
() => {
|
||||
let li = $(`.dropdown-menu li:contains("${text}"):visible`).get(0);
|
||||
$(li).find(`a`).click();
|
||||
},
|
||||
() => frappe.timeout(1)
|
||||
]);
|
||||
},
|
||||
click_desktop_icon: (text) => {
|
||||
// Method to click the desktop icons on the Desk, by their name
|
||||
return frappe.run_serially([
|
||||
() => $("#icon-grid > div > div.app-icon[title="+text+"]").click(),
|
||||
() => frappe.timeout(1)
|
||||
]);
|
||||
},
|
||||
is_visible: (text, tag='a') => {
|
||||
// Method to check the visibility of an element
|
||||
return $(`${tag}:contains("${text}")`).is(`:visible`);
|
||||
},
|
||||
/**
|
||||
* Clicks a button on a form.
|
||||
* @param {String} text - The button's text
|
||||
* @return {frappe.timeout}
|
||||
* @throws will throw an exception if a matching visible button is not found
|
||||
*/
|
||||
click_button: function(text) {
|
||||
let element = $(`.btn:contains("${text}"):visible`);
|
||||
if(!element.length) {
|
||||
throw `did not find any button containing ${text}`;
|
||||
}
|
||||
element.click();
|
||||
return frappe.timeout(0.5);
|
||||
},
|
||||
/**
|
||||
* Clicks a link on a form.
|
||||
* @param {String} text - The text of the link to be clicked
|
||||
* @return {frappe.timeout}
|
||||
* @throws will throw an exception if a link with the given text is not found
|
||||
*/
|
||||
click_link: function(text) {
|
||||
let element = $(`a:contains("${text}"):visible`);
|
||||
if(!element.length) {
|
||||
throw `did not find any link containing ${text}`;
|
||||
}
|
||||
element.get(0).click();
|
||||
return frappe.timeout(0.5);
|
||||
},
|
||||
/**
|
||||
* Sets the given control to the value given.
|
||||
* @param {String} fieldname - The Doctype's field name
|
||||
* @param {String} value - The value the control should be changed to
|
||||
* @return {frappe.timeout}
|
||||
* @throws will throw an exception if the field is not found or is not visible
|
||||
*/
|
||||
set_control: function(fieldname, value) {
|
||||
let control = $(`.form-control[data-fieldname="${fieldname}"]:visible`);
|
||||
if(!control.length) {
|
||||
throw `did not find any control with fieldname ${fieldname}`;
|
||||
}
|
||||
control.val(value).trigger('change');
|
||||
return frappe.timeout(0.5);
|
||||
},
|
||||
/**
|
||||
* Checks if given field is disabled.
|
||||
* @param {String} fieldname - The Doctype field name
|
||||
* @return {Boolean} true if condition is met
|
||||
* @throws will throw an exception if the field is not found or is not a form control
|
||||
*/
|
||||
is_disabled_field: function(fieldname){
|
||||
let control = $(`.form-control[data-fieldname="${fieldname}"]:disabled`);
|
||||
if(!control.length) {
|
||||
throw `did not find any control with fieldname ${fieldname}`;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
QUnit.module('views');
|
||||
|
||||
QUnit.test("Calendar View Tests", function(assert) {
|
||||
assert.expect(3);
|
||||
let done = assert.async();
|
||||
let random_text = frappe.utils.get_random(3);
|
||||
let today = frappe.datetime.get_today()+" 16:20:35"; //arbitrary value taken to prevent cases like 12a for 12:00am and 12h to 24h conversion
|
||||
let visible_time = () => {
|
||||
// Method to return the start-time (hours) of the event visible
|
||||
return $('.fc-time').text().split('p')[0]; // 'p' because the arbitrary time is pm
|
||||
};
|
||||
let event_title_text = () => {
|
||||
// Method to return the title of the event visible
|
||||
return $('.fc-title:visible').text();
|
||||
};
|
||||
|
||||
frappe.run_serially([
|
||||
// create 2 events, one private, one public
|
||||
() => frappe.tests.make("Event", [
|
||||
{subject: random_text + ':Pri'},
|
||||
{starts_on: today},
|
||||
{event_type: 'Private'}
|
||||
]),
|
||||
|
||||
() => frappe.timeout(1),
|
||||
|
||||
() => frappe.tests.make("Event", [
|
||||
{subject: random_text + ':Pub'},
|
||||
{starts_on: today},
|
||||
{event_type: 'Public'}
|
||||
]),
|
||||
|
||||
() => frappe.timeout(1),
|
||||
|
||||
// Goto Calendar view
|
||||
() => frappe.set_route(["List", "Event", "Calendar"]),
|
||||
|
||||
// clear filter
|
||||
() => cur_list.filter_area.remove('event_type'),
|
||||
() => frappe.timeout(2),
|
||||
// Check if event is created
|
||||
() => {
|
||||
// Check if the event exists and if its title matches with the one created
|
||||
assert.ok(event_title_text().includes(random_text + ':Pri'),
|
||||
"Event title verified");
|
||||
},
|
||||
|
||||
// check filter
|
||||
() => cur_list.filter_area.add('Event', 'event_type', '=', 'Public'),
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
// private event should be hidden
|
||||
assert.notOk(event_title_text().includes(random_text + ':Pri'),
|
||||
"Event title verified");
|
||||
},
|
||||
|
||||
// Delete event
|
||||
// Goto Calendar view
|
||||
() => frappe.set_route(["List", "Event", "Calendar"]),
|
||||
() => frappe.timeout(1),
|
||||
// delete event
|
||||
() => frappe.click_link(random_text + ':Pub'),
|
||||
() => {
|
||||
frappe.tests.click_page_head_item('Menu');
|
||||
frappe.tests.click_dropdown_item('Delete');
|
||||
},
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.click_button('Yes'),
|
||||
() => frappe.timeout(2),
|
||||
() => frappe.set_route(["List", "Event", "Calendar"]),
|
||||
() => frappe.click_button("Refresh"),
|
||||
() => frappe.timeout(1),
|
||||
|
||||
// Check if event is deleted
|
||||
() => assert.notOk(event_title_text().includes(random_text + ':Pub'),
|
||||
"Event deleted"),
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
QUnit.module('controls');
|
||||
|
||||
QUnit.test("Test ControlGeolocation", function(assert) {
|
||||
assert.expect(1);
|
||||
|
||||
const random_name = frappe.utils.get_random(3).toLowerCase();
|
||||
|
||||
let done = assert.async();
|
||||
|
||||
// geolocation alert dialog suppressed (only secure origins or localhost allowed)
|
||||
window.alert = function() {
|
||||
console.log.apply(console, arguments); //eslint-disable-line
|
||||
};
|
||||
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
return frappe.tests.make('Custom Field', [
|
||||
{dt: 'ToDo'},
|
||||
{fieldtype: 'Geolocation'},
|
||||
{label: random_name},
|
||||
]);
|
||||
},
|
||||
() => frappe.set_route('List', 'ToDo'),
|
||||
() => frappe.new_doc('ToDo'),
|
||||
() => {
|
||||
if (frappe.quick_entry)
|
||||
{
|
||||
frappe.quick_entry.dialog.$wrapper.find('.edit-full').click();
|
||||
return frappe.timeout(1);
|
||||
}
|
||||
},
|
||||
() => {
|
||||
const control = $(`.frappe-control[data-fieldname="${random_name}"]`);
|
||||
|
||||
return assert.ok(control.data('fieldtype') === 'Geolocation');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
QUnit.module('controls');
|
||||
|
||||
QUnit.test("Test ControlHTML", function(assert) {
|
||||
assert.expect(3);
|
||||
const random_name = frappe.utils.get_random(3).toLowerCase();
|
||||
|
||||
let done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
return frappe.tests.make('Custom Field', [
|
||||
{dt: 'ToDo'},
|
||||
{fieldtype: 'HTML'},
|
||||
{label: random_name},
|
||||
{options: '<h3> Test </h3>'}
|
||||
]);
|
||||
},
|
||||
() => {
|
||||
return frappe.tests.make('Custom Field', [
|
||||
{dt: 'ToDo'},
|
||||
{fieldtype: 'HTML'},
|
||||
{label: random_name + "_template"},
|
||||
{options: '<h3> Test {{ doc.status }} </h3>'}
|
||||
]);
|
||||
},
|
||||
() => frappe.set_route('List', 'ToDo'),
|
||||
() => frappe.new_doc('ToDo'),
|
||||
() => {
|
||||
if (frappe.quick_entry)
|
||||
{
|
||||
frappe.quick_entry.dialog.$wrapper.find('.edit-full').click();
|
||||
return frappe.timeout(1);
|
||||
}
|
||||
},
|
||||
() => {
|
||||
const control = $(`.frappe-control[data-fieldname="${random_name}"]`)[0];
|
||||
|
||||
return assert.ok(control.innerHTML === '<h3> Test </h3>');
|
||||
},
|
||||
() => {
|
||||
const control = $(`.frappe-control[data-fieldname="${random_name}_template"]`)[0];
|
||||
// refresh input must be called independently
|
||||
cur_frm.get_field(`${random_name}_template`).refresh_input();
|
||||
|
||||
return assert.ok(control.innerHTML === '<h3> Test Open </h3>');
|
||||
},
|
||||
() => frappe.tests.set_control("status", "Closed"),
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
const control = $(`.frappe-control[data-fieldname="${random_name}_template"]`)[0];
|
||||
// refresh input must be called independently
|
||||
cur_frm.get_field(`${random_name}_template`).refresh_input();
|
||||
return assert.ok(control.innerHTML === '<h3> Test Closed </h3>');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
QUnit.module('views');
|
||||
|
||||
QUnit.test("Test: Setting column colour [Kanban view]", function(assert) {
|
||||
assert.expect(3);
|
||||
let done = assert.async();
|
||||
function get_column(name, colour) {
|
||||
return ('.kanban-column:contains('+name+')>div>div>ul>li>div.'+colour);
|
||||
}
|
||||
|
||||
frappe.run_serially([
|
||||
() => frappe.set_route("List", "ToDo", "Kanban", "Kanban test"),
|
||||
() => frappe.timeout(1),
|
||||
() => assert.deepEqual(["List", "ToDo", "Kanban", "Kanban test"], frappe.get_route(),
|
||||
"Kanban view opened successfully."),
|
||||
() => {
|
||||
// set colour for columns
|
||||
$(get_column('High', "red")).click();
|
||||
$(get_column('Medium', "green")).click();
|
||||
$(get_column('Low', "yellow")).click();
|
||||
},
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
//check if different colours are set
|
||||
assert.equal($('.red > span')[0].innerText, 'High',
|
||||
"Colour is set for kanban column.");
|
||||
assert.equal($('.green > span')[0].innerText, 'Medium',
|
||||
"Different colour is set for other column.");
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
QUnit.module('views');
|
||||
|
||||
QUnit.test("Test: Creation [Kanban view]", function(assert) {
|
||||
assert.expect(2);
|
||||
let done = assert.async();
|
||||
|
||||
const board_name = 'Kanban test';
|
||||
|
||||
frappe.run_serially([
|
||||
() => frappe.set_route("List", "ToDo", "List"),
|
||||
// wait for cur_list to initialize
|
||||
() => cur_list.init(),
|
||||
// click kanban in side bar
|
||||
() => frappe.tests.click_link('Kanban'),
|
||||
() => frappe.tests.click_link('New Kanban Board'),
|
||||
() => frappe.timeout(0.5),
|
||||
// create new kanban
|
||||
() => {
|
||||
assert.equal(cur_dialog.title, 'New Kanban Board',
|
||||
"Dialog for new kanban opened.");
|
||||
cur_dialog.set_value('board_name', board_name);
|
||||
cur_dialog.set_value('field_name', 'Priority');
|
||||
},
|
||||
() => frappe.timeout(0.5),
|
||||
() => cur_dialog.get_primary_btn().click(),
|
||||
() => frappe.timeout(1),
|
||||
() => frappe.set_route("List", "Kanban Board", "List"),
|
||||
() => frappe.timeout(0.5),
|
||||
// check in kanban list if new kanban is created
|
||||
() => assert.equal(cur_list.data[0].name, board_name,
|
||||
"Added kanban is visible in kanban list."),
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
QUnit.module('views');
|
||||
|
||||
QUnit.test("Test: Filters [Kanban view]", function(assert) {
|
||||
assert.expect(3);
|
||||
let done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
() => frappe.set_route("List", "ToDo", "Kanban", "Kanban test"),
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
assert.deepEqual(["List", "ToDo", "Kanban", "Kanban test"], frappe.get_route(),
|
||||
"Kanban view opened successfully.");
|
||||
},
|
||||
// set filter values
|
||||
() => cur_list.filter_area.add('ToDo', 'priority', '=', 'Low'),
|
||||
() => frappe.timeout(1),
|
||||
() => cur_list.page.btn_secondary.click(),
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
assert.equal(cur_list.data[0].priority, 'Low',
|
||||
'visible element has low priority');
|
||||
let non_low_items = cur_list.data.filter(d => d.priority != 'Low');
|
||||
assert.equal(non_low_items.length, 0, 'No item without low priority');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
QUnit.module('views');
|
||||
|
||||
QUnit.test("Test: Kanban view", function(assert) {
|
||||
assert.expect(4);
|
||||
let done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
() => frappe.set_route("List", "ToDo", "List"),
|
||||
// calculate number of element in list
|
||||
() => frappe.timeout(1),
|
||||
() => frappe.set_route("List", "ToDo", "Kanban", "Kanban test"),
|
||||
() => frappe.timeout(2),
|
||||
() => {
|
||||
assert.equal('Kanban', cur_list.view_name,
|
||||
"Current view is kanban.");
|
||||
assert.equal("Kanban test", cur_list.page_title,
|
||||
"Kanban view opened successfully.");
|
||||
// check if all elements are visible in kanban view
|
||||
const $high_priority_cards =
|
||||
$('.kanban-column[data-column-value="High"] .kanban-card-wrapper');
|
||||
const $low_priority_cards =
|
||||
$('.kanban-column[data-column-value="Low"] .kanban-card-wrapper');
|
||||
|
||||
assert.equal($high_priority_cards.length, 1);
|
||||
assert.equal($low_priority_cards.length, 1);
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
QUnit.module('form');
|
||||
|
||||
QUnit.test("Test Linked With", function(assert) {
|
||||
assert.expect(2);
|
||||
const done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
() => frappe.set_route('Form', 'Module Def', 'Contacts'),
|
||||
() => frappe.tests.click_page_head_item('Menu'),
|
||||
() => frappe.tests.click_dropdown_item('Links'),
|
||||
() => frappe.timeout(4),
|
||||
() => {
|
||||
assert.equal(cur_dialog.title, 'Linked With', 'Linked with dialog is opened');
|
||||
const link_tables_count = cur_dialog.$wrapper.find('.list-item-table').length;
|
||||
assert.equal(link_tables_count, 2, 'Two DocTypes are linked with Contacts');
|
||||
},
|
||||
done
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
QUnit.module('views');
|
||||
|
||||
QUnit.test("Test list filters", function(assert) {
|
||||
assert.expect(3);
|
||||
let done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
return frappe.tests.make('ToDo', [
|
||||
{description: 'low priority'},
|
||||
{priority: 'Low'}
|
||||
]);
|
||||
},
|
||||
() => {
|
||||
return frappe.tests.make('ToDo', [
|
||||
{description: 'high priority'},
|
||||
{priority: 'High'}
|
||||
]);
|
||||
},
|
||||
() => frappe.set_route('List', 'ToDo', 'List'),
|
||||
() => frappe.timeout(0.5),
|
||||
() => {
|
||||
assert.deepEqual(['List', 'ToDo', 'List'], frappe.get_route(),
|
||||
"List opened successfully.");
|
||||
//set filter values
|
||||
return frappe.set_control('priority', 'Low');
|
||||
},
|
||||
() => frappe.timeout(0.5),
|
||||
() => cur_list.page.btn_secondary.click(),
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
assert.equal(cur_list.data[0].priority, 'Low',
|
||||
'visible element has low priority');
|
||||
let non_low_items = cur_list.data.filter(d => d.priority != 'Low');
|
||||
assert.equal(non_low_items.length, 0, 'no item without low priority');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
QUnit.module('views');
|
||||
|
||||
QUnit.test("Test paging in list view", function(assert) {
|
||||
assert.expect(5);
|
||||
let done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
() => frappe.set_route('List', 'DocType'),
|
||||
() => frappe.timeout(0.5),
|
||||
() => assert.deepEqual(['List', 'DocType', 'List'], frappe.get_route(),
|
||||
"List opened successfully."),
|
||||
//check elements less then page length [20 in this case]
|
||||
() => assert.equal(cur_list.data.length, 20, 'show 20 items'),
|
||||
() => frappe.click_button('More'),
|
||||
() => frappe.timeout(2),
|
||||
() => assert.equal(cur_list.data.length, 40, 'show more items'),
|
||||
() => frappe.tests.click_button('100'),
|
||||
() => frappe.timeout(2),
|
||||
() => assert.ok(cur_list.data.length > 40, 'show 100 items'),
|
||||
() => frappe.tests.click_button('20'),
|
||||
() => frappe.timeout(2),
|
||||
() => assert.equal(cur_list.data.length, 20, 'show 20 items again'),
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
QUnit.module('Setup');
|
||||
|
||||
QUnit.test("Test List Count", function(assert) {
|
||||
assert.expect(3);
|
||||
const done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
() => frappe.set_route('List', 'DocType'),
|
||||
() => frappe.timeout(0.5),
|
||||
() => {
|
||||
let count = $('.list-count').text().split(' ')[0];
|
||||
assert.equal(cur_list.data.length, count, "Correct Count");
|
||||
},
|
||||
|
||||
() => frappe.timeout(1),
|
||||
() => cur_list.filter_area.add('Doctype', 'module', '=', 'Desk'),
|
||||
() => frappe.click_button('Refresh'),
|
||||
() => {
|
||||
let count = $('.list-count').text().split(' ')[0];
|
||||
assert.equal(cur_list.data.length, count, "Correct Count");
|
||||
},
|
||||
|
||||
() => cur_list.filter_area.clear(),
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
cur_list.filter_area.add('DocField', 'fieldname', 'like', 'owner');
|
||||
let count = $('.list-count').text().split(' ')[0];
|
||||
assert.equal(cur_list.data.length, count, "Correct Count");
|
||||
},
|
||||
|
||||
done
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
QUnit.module('views');
|
||||
|
||||
QUnit.test("Test modules view", function(assert) {
|
||||
assert.expect(4);
|
||||
let done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
|
||||
//click Document Share Report in Permissions section [Report]
|
||||
() => frappe.set_route("modules", "Setup"),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.click_link('Document Share Report'),
|
||||
() => assert.deepEqual(frappe.get_route(), ["List", "DocShare", "Report", "Document Share Report"],
|
||||
'document share report'),
|
||||
|
||||
//click Print Setting in Printing section [Form]
|
||||
() => frappe.set_route("modules", "Setup"),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.click_link('Print Settings'),
|
||||
() => assert.deepEqual(frappe.get_route(), ["Form", "Print Settings"],
|
||||
'print settings'),
|
||||
|
||||
//click Workflow Action in Workflow section [List]
|
||||
() => frappe.set_route("modules", "Setup"),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.click_link('Workflow Action'),
|
||||
() => assert.deepEqual(frappe.get_route(), ["List", "Workflow Action", "List"],
|
||||
'workflow action'),
|
||||
|
||||
//click Workflow Action in Workflow section [List]
|
||||
() => frappe.set_route("modules"),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.click_link('Tools'),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.click_link('To Do'),
|
||||
() => assert.deepEqual(frappe.get_route(), ["List", "ToDo", "List"],
|
||||
'todo list'),
|
||||
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// MIT License. See license.txt
|
||||
|
||||
QUnit.module("Number Formatting");
|
||||
|
||||
QUnit.test("#,###.##", function(assert) {
|
||||
assert.equal(format_number(100, "#,###.##"), "100.00");
|
||||
assert.equal(format_number(1000, "#,###.##"), "1,000.00");
|
||||
assert.equal(format_number(10000, "#,###.##"), "10,000.00");
|
||||
assert.equal(format_number(1000000, "#,###.##"), "1,000,000.00");
|
||||
assert.equal(format_number(1000000.345, "#,###.##"), "1,000,000.35");
|
||||
});
|
||||
|
||||
QUnit.test("#,##,###.##", function(assert) {
|
||||
assert.equal(format_number(100, "#,##,###.##"), "100.00");
|
||||
assert.equal(format_number(1000, "#,##,###.##"), "1,000.00");
|
||||
assert.equal(format_number(10000, "#,##,###.##"), "10,000.00");
|
||||
assert.equal(format_number(1000000, "#,##,###.##"), "10,00,000.00");
|
||||
assert.equal(format_number(1000000.341, "#,##,###.##"), "10,00,000.34");
|
||||
assert.equal(format_number(10000000.341, "#,##,###.##"), "1,00,00,000.34");
|
||||
});
|
||||
|
||||
QUnit.test("#.###,##", function(assert) {
|
||||
assert.equal(format_number(100, "#.###,##"), "100,00");
|
||||
assert.equal(format_number(1000, "#.###,##"), "1.000,00");
|
||||
assert.equal(format_number(10000, "#.###,##"), "10.000,00");
|
||||
assert.equal(format_number(1000000, "#.###,##"), "1.000.000,00");
|
||||
assert.equal(format_number(1000000.345, "#.###,##"), "1.000.000,35");
|
||||
});
|
||||
|
||||
QUnit.test("#.###", function(assert) {
|
||||
assert.equal(format_number(100, "#.###"), "100");
|
||||
assert.equal(format_number(1000, "#.###"), "1.000");
|
||||
assert.equal(format_number(10000, "#.###"), "10.000");
|
||||
assert.equal(format_number(-100000, "#.###"), "-100.000");
|
||||
assert.equal(format_number(1000000, "#.###"), "1.000.000");
|
||||
assert.equal(format_number(1000000.345, "#.###"), "1.000.000");
|
||||
});
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest, frappe, time
|
||||
from frappe.utils.selenium_testdriver import TestDriver
|
||||
|
||||
class TestSocialLoginKeyButtons(unittest.TestCase):
|
||||
def setUp(self):
|
||||
try:
|
||||
frappe_login_key = frappe.get_doc("Social Login Key", "frappe")
|
||||
except frappe.DoesNotExistError:
|
||||
frappe_login_key = frappe.new_doc("Social Login Key")
|
||||
frappe_login_key.get_social_login_provider("Frappe", initialize=True)
|
||||
frappe_login_key.base_url = "http://localhost:8000"
|
||||
frappe_login_key.enable_social_login = 1
|
||||
frappe_login_key.client_id = "test_client_id"
|
||||
frappe_login_key.client_secret = "test_client_secret"
|
||||
frappe_login_key.save()
|
||||
|
||||
self.driver = TestDriver()
|
||||
|
||||
def test_login_buttons(self):
|
||||
|
||||
# Go to Login Page
|
||||
self.driver.get("login")
|
||||
|
||||
time.sleep(2)
|
||||
frappe_social_login = self.driver.find(".btn-frappe")
|
||||
self.assertTrue(len(frappe_social_login) > 0)
|
||||
|
||||
def tearDown(self):
|
||||
self.driver.close()
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
from __future__ import print_function, unicode_literals
|
||||
from frappe.utils.selenium_testdriver import TestDriver
|
||||
import unittest, os, frappe, time
|
||||
|
||||
class TestTestRunner(unittest.TestCase):
|
||||
def test_test_runner(self):
|
||||
if frappe.flags.run_setup_wizard_ui_test:
|
||||
for setup_wizard_test in frappe.get_hooks("setup_wizard_test"):
|
||||
passed = frappe.get_attr(setup_wizard_test)()
|
||||
self.assertTrue(passed)
|
||||
return
|
||||
|
||||
driver = TestDriver()
|
||||
frappe.db.set_default('in_selenium', '1')
|
||||
driver.login()
|
||||
for test in get_tests():
|
||||
if test.startswith('#'):
|
||||
continue
|
||||
|
||||
timeout = 60
|
||||
passed = False
|
||||
if '#' in test:
|
||||
test, comment = test.split('#')
|
||||
test = test.strip()
|
||||
if comment.strip()=='long':
|
||||
timeout = 300
|
||||
|
||||
print('Running {0}...'.format(test))
|
||||
|
||||
frappe.db.set_value('Test Runner', None, 'module_path', test)
|
||||
frappe.db.commit()
|
||||
driver.refresh()
|
||||
driver.set_route('Form', 'Test Runner')
|
||||
try:
|
||||
driver.click_primary_action()
|
||||
driver.wait_for('#frappe-qunit-done', timeout=timeout)
|
||||
console = driver.get_console()
|
||||
passed = 'Tests Passed' in console
|
||||
finally:
|
||||
console = driver.get_console()
|
||||
passed = 'Test Passed' in console
|
||||
if frappe.flags.tests_verbose or not passed:
|
||||
for line in console:
|
||||
print(line)
|
||||
print('-' * 40)
|
||||
else:
|
||||
self.assertTrue(passed)
|
||||
time.sleep(1)
|
||||
frappe.db.set_default('in_selenium', None)
|
||||
driver.close()
|
||||
|
||||
def get_tests():
|
||||
'''Get tests base on flag'''
|
||||
frappe.db.set_value('Test Runner', None, 'app', frappe.flags.ui_test_app or '')
|
||||
|
||||
if frappe.flags.ui_test_list:
|
||||
# list of tests
|
||||
return get_tests_for(test_list=frappe.flags.ui_test_list)
|
||||
elif frappe.flags.ui_test_path:
|
||||
# specific test
|
||||
return (frappe.flags.ui_test_path,)
|
||||
elif frappe.flags.ui_test_app:
|
||||
# specific app
|
||||
return get_tests_for(frappe.flags.ui_test_app)
|
||||
else:
|
||||
# all apps
|
||||
tests = []
|
||||
for app in frappe.get_installed_apps():
|
||||
tests.extend(get_tests_for(app))
|
||||
return tests
|
||||
|
||||
def get_tests_for(app=None, test_list=None):
|
||||
tests = []
|
||||
if test_list:
|
||||
# Get all tests from a particular txt file
|
||||
app, test_list = test_list.split(os.path.sep, 1)
|
||||
tests_path = frappe.get_app_path(app, test_list)
|
||||
else:
|
||||
# Get all tests for a particular app
|
||||
tests_path = frappe.get_app_path(app, 'tests', 'ui', 'tests.txt')
|
||||
if os.path.exists(tests_path):
|
||||
with open(tests_path, 'r') as fileobj:
|
||||
tests = fileobj.read().strip().splitlines()
|
||||
return tests
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
from __future__ import print_function, unicode_literals
|
||||
from frappe.utils.selenium_testdriver import TestDriver
|
||||
import unittest
|
||||
import time, os
|
||||
|
||||
class TestToDo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.driver = TestDriver()
|
||||
|
||||
def test_todo(self):
|
||||
self.driver.login()
|
||||
|
||||
# list view
|
||||
self.driver.set_route('List', 'ToDo')
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# new
|
||||
self.driver.click_primary_action()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# set input
|
||||
self.driver.set_text_editor('description', 'hello')
|
||||
|
||||
# save
|
||||
self.driver.click_modal_primary_action()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# refresh
|
||||
self.driver.click_secondary_action()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
result_list = self.driver.get_visible_element('.result-list')
|
||||
first_element_text = (result_list
|
||||
.find_element_by_css_selector('.list-item')
|
||||
.find_element_by_css_selector('.list-id').text)
|
||||
|
||||
# if os.environ.get('CI'):
|
||||
# # we don't run this test in Travis as it always fails
|
||||
# # reinforcing why we use Unit Testing instead of integration
|
||||
# # testing
|
||||
# return
|
||||
|
||||
self.assertTrue('hello' in first_element_text)
|
||||
|
||||
def tearDown(self):
|
||||
self.driver.close()
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
frappe/tests/ui/test_number_format.js
|
||||
frappe/tests/ui/test_list/test_list_filter.js
|
||||
frappe/tests/ui/test_list/test_list_paging.js
|
||||
frappe/tests/ui/test_module_view.js
|
||||
frappe/tests/ui/test_calendar_view.js
|
||||
frappe/tests/ui/test_kanban/test_kanban_creation.js
|
||||
frappe/tests/ui/test_kanban/test_kanban_view.js
|
||||
frappe/tests/ui/test_kanban/test_kanban_filters.js
|
||||
frappe/tests/ui/test_kanban/test_kanban_column.js
|
||||
frappe/core/doctype/report/test_query_report.js
|
||||
frappe/tests/ui/test_linked_with.js
|
||||
frappe/custom/doctype/customize_form/test_customize_form.js
|
||||
frappe/desk/doctype/event/test_event.js
|
||||
frappe/tests/ui/test_control_html.js
|
||||
frappe/tests/ui/test_control_geolocation.js
|
||||
frappe/core/doctype/role_profile/test_role_profile.js
|
||||
frappe/core/doctype/user/test_user_with_role_profile.js
|
||||
frappe/tests/ui/test_list_count.js
|
||||
frappe/workflow/doctype/workflow/tests/test_workflow_create.js
|
||||
frappe/workflow/doctype/workflow/tests/test_workflow_test.js
|
||||
|
|
@ -1,299 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
#from selenium.webdriver.support.select import Select
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
#from selenium.common.exceptions import TimeoutException
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||
|
||||
import time
|
||||
import signal
|
||||
import os, sys
|
||||
import frappe
|
||||
from ast import literal_eval
|
||||
|
||||
class TestDriver(object):
|
||||
def __init__(self, port=None):
|
||||
self.port = port or frappe.get_site_config().webserver_port or '8000'
|
||||
|
||||
chrome_options = Options()
|
||||
capabilities = DesiredCapabilities.CHROME
|
||||
|
||||
if os.environ.get('CI'):
|
||||
self.host = 'localhost'
|
||||
else:
|
||||
self.host = frappe.local.site
|
||||
|
||||
# enable browser logging
|
||||
capabilities['loggingPrefs'] = {'browser':'ALL'}
|
||||
|
||||
chrome_options.add_argument('--no-sandbox')
|
||||
chrome_options.add_argument('--start-maximized')
|
||||
self.driver = webdriver.Chrome(chrome_options=chrome_options,
|
||||
desired_capabilities=capabilities, port=9515)
|
||||
|
||||
# self.driver.set_window_size(1080,800)
|
||||
self.cur_route = None
|
||||
self.logged_in = False
|
||||
|
||||
@property
|
||||
def localhost(self):
|
||||
return "http://{host}:{port}".format(host=self.host, port=self.port)
|
||||
|
||||
def get(self, url):
|
||||
return self.driver.get(os.path.join(self.localhost, url))
|
||||
|
||||
def start(self):
|
||||
def signal_handler(signal, frame):
|
||||
self.close()
|
||||
sys.exit(0)
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
def refresh(self):
|
||||
self.driver.refresh()
|
||||
|
||||
def close(self):
|
||||
if self.driver:
|
||||
self.driver.quit()
|
||||
self.driver = None
|
||||
|
||||
def login(self, wait_for_id="#page-desktop", animate=0, scroll_offset=0):
|
||||
if self.logged_in:
|
||||
return
|
||||
self.get('login')
|
||||
self.wait_for("#login_email")
|
||||
self.set_input("#login_email", "Administrator")
|
||||
self.set_input("#login_password", "admin")
|
||||
self.click('.btn-login', animate=animate, offset=scroll_offset)
|
||||
self.wait_for(wait_for_id)
|
||||
self.logged_in = True
|
||||
|
||||
def set_input(self, selector, text, key=None, xpath=None):
|
||||
elem = self.find(selector, xpath=xpath)[0]
|
||||
elem.clear()
|
||||
elem.send_keys(text)
|
||||
if key:
|
||||
time.sleep(0.5)
|
||||
elem.send_keys(key)
|
||||
time.sleep(0.2)
|
||||
|
||||
def set_field(self, fieldname, text):
|
||||
elem = self.wait_for(xpath='//input[@data-fieldname="{0}"]'.format(fieldname))
|
||||
time.sleep(0.2)
|
||||
elem.send_keys(text)
|
||||
|
||||
def set_select(self, fieldname, text):
|
||||
elem = self.wait_for(xpath='//select[@data-fieldname="{0}"]'.format(fieldname))
|
||||
time.sleep(0.2)
|
||||
elem.send_keys(text)
|
||||
|
||||
def set_multicheck(self, fieldname, values):
|
||||
for value in values:
|
||||
path = '//div[@data-fieldname="{0}"]//span[@data-unit="{1}"]'.format(fieldname, value)
|
||||
elem = self.wait_for(xpath=path)
|
||||
time.sleep(0.2)
|
||||
elem.click()
|
||||
|
||||
def set_text_editor(self, fieldname, text):
|
||||
elem = self.wait_for(xpath='//div[@data-fieldname="{0}"]//div[@contenteditable="true"]'.format(fieldname))
|
||||
time.sleep(0.2)
|
||||
elem.send_keys(text)
|
||||
|
||||
def find(self, selector=None, everywhere=False, xpath=None):
|
||||
if xpath:
|
||||
return self.driver.find_elements_by_xpath(xpath)
|
||||
else:
|
||||
if self.cur_route and not everywhere:
|
||||
selector = self.cur_route + " " + selector
|
||||
return self.driver.find_elements_by_css_selector(selector)
|
||||
|
||||
def wait_for(self, selector=None, everywhere=False, timeout=20, xpath=None, for_invisible=False):
|
||||
if self.cur_route and not everywhere:
|
||||
selector = self.cur_route + " " + selector
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
if selector:
|
||||
_by = By.CSS_SELECTOR
|
||||
if xpath:
|
||||
_by = By.XPATH
|
||||
selector = xpath
|
||||
|
||||
try:
|
||||
if not for_invisible:
|
||||
elem = self.get_wait(timeout).until(
|
||||
EC.presence_of_element_located((_by, selector)))
|
||||
else:
|
||||
elem = self.get_wait(timeout).until(
|
||||
EC.invisibility_of_element_located((_by, selector)))
|
||||
return elem
|
||||
except Exception as e:
|
||||
# body = self.driver.find_element_by_id('body_div')
|
||||
# print(body.get_attribute('innerHTML'))
|
||||
self.print_console()
|
||||
raise e
|
||||
|
||||
def wait_for_invisible(self, selector=None, everywhere=False, timeout=20, xpath=None):
|
||||
self.wait_for(selector, everywhere, timeout, xpath, True)
|
||||
|
||||
def get_console(self):
|
||||
out = []
|
||||
for entry in self.driver.get_log('browser'):
|
||||
source, line_no, message = entry.get('message').split(' ', 2)
|
||||
|
||||
if message and message[0] in ('"', "'"):
|
||||
# message is a quoted/escaped string
|
||||
message = literal_eval(message)
|
||||
|
||||
out.append(source + ' ' + line_no)
|
||||
out.append(message)
|
||||
out.append('-'*40)
|
||||
|
||||
return out
|
||||
|
||||
def print_console(self):
|
||||
for line in self.get_console():
|
||||
print(line)
|
||||
|
||||
def get_wait(self, timeout=20):
|
||||
return WebDriverWait(self.driver, timeout)
|
||||
|
||||
def scroll_to(self, selector, animate=0, offset=0):
|
||||
self.execute_script("frappe.ui.scroll('{0}', {1}, {2})".format(selector, animate, offset))
|
||||
|
||||
def set_route(self, *args):
|
||||
self.execute_script('frappe.set_route({0})'\
|
||||
.format(', '.join(['"{0}"'.format(r) for r in args])))
|
||||
|
||||
self.wait_for(xpath='//div[@data-page-route="{0}"]'.format('/'.join(args)), timeout=4)
|
||||
|
||||
def click(self, css_selector, xpath=None, timeout=20, animate=0, offset=0):
|
||||
element = self.wait_till_clickable(css_selector, xpath, timeout)
|
||||
self.scroll_to(css_selector, animate, offset)
|
||||
time.sleep(0.5)
|
||||
element.click()
|
||||
return element
|
||||
|
||||
def click_primary_action(self):
|
||||
selector = ".page-actions .primary-action"
|
||||
#self.scroll_to(selector)
|
||||
self.wait_till_clickable(selector).click()
|
||||
self.wait_for_ajax()
|
||||
|
||||
def click_secondary_action(self):
|
||||
selector = ".page-actions .btn-secondary"
|
||||
#self.scroll_to(selector)
|
||||
self.wait_till_clickable(selector).click()
|
||||
self.wait_for_ajax()
|
||||
|
||||
def click_modal_primary_action(self):
|
||||
self.get_visible_modal().find_element_by_css_selector('.btn-primary').click()
|
||||
|
||||
def get_visible_modal(self):
|
||||
return self.get_visible_element('.modal-content')
|
||||
|
||||
def get_visible_element(self, selector=None, xpath=None):
|
||||
for elem in self.find(selector=selector, xpath=xpath):
|
||||
if elem.is_displayed():
|
||||
return elem
|
||||
|
||||
def wait_till_clickable(self, selector=None, xpath=None, timeout=20):
|
||||
if self.cur_route:
|
||||
selector = self.cur_route + " " + selector
|
||||
|
||||
by = By.CSS_SELECTOR
|
||||
if xpath:
|
||||
by = By.XPATH
|
||||
selector = xpath
|
||||
|
||||
return self.get_wait(timeout).until(EC.element_to_be_clickable(
|
||||
(by, selector)))
|
||||
|
||||
|
||||
def execute_script(self, js):
|
||||
self.driver.execute_script(js)
|
||||
|
||||
def wait_for_ajax(self, freeze = False):
|
||||
self.wait_for('body[data-ajax-state="complete"]', True)
|
||||
if freeze:
|
||||
self.wait_for_invisible(".freeze-message-container")
|
||||
|
||||
|
||||
# def go_to_module(module_name, item=None):
|
||||
# global cur_route
|
||||
#
|
||||
# # desktop
|
||||
# find(".navbar-home", True)[0].click()
|
||||
# cur_route = None
|
||||
# wait("#page-desktop")
|
||||
#
|
||||
# page = "Module/" + module_name
|
||||
# m = find('#page-desktop [data-link="{0}"] .app-icon'.format(page))
|
||||
# if not m:
|
||||
# page = "List/" + module_name
|
||||
# m = find('#page-desktop [data-link="{0}"] .app-icon'.format(page))
|
||||
# if not m:
|
||||
# raise Exception("Module {0} not found".format(module_name))
|
||||
#
|
||||
# m[0].click()
|
||||
# wait_for_page(page)
|
||||
#
|
||||
# if item:
|
||||
# elem = find('[data-label="{0}"]'.format(item))[0]
|
||||
# elem.click()
|
||||
# page = elem.get_attribute("data-route")
|
||||
# wait_for_page(page)
|
||||
#
|
||||
# def new_doc(module, doctype):
|
||||
# go_to_module(module, doctype)
|
||||
# primary_action()
|
||||
# wait_for_page("Form/" + doctype)
|
||||
#
|
||||
# def add_child(fieldname):
|
||||
# find('[data-fieldname="{0}"] .grid-add-row'.format(fieldname))[0].click()
|
||||
# wait('[data-fieldname="{0}"] .form-grid'.format(fieldname))
|
||||
#
|
||||
# def done_add_child(fieldname):
|
||||
# selector = '[data-fieldname="{0}"] .grid-row-open .btn-success'.format(fieldname)
|
||||
# scroll_to(selector)
|
||||
# wait_till_clickable(selector).click()
|
||||
#
|
||||
# def set_field(fieldname, value, fieldtype="input"):
|
||||
# _driver.switch_to.window(_driver.current_window_handle)
|
||||
# selector = '{0}[data-fieldname="{1}"]'.format(fieldtype, fieldname)
|
||||
# set_input(selector, value, key=Keys.TAB)
|
||||
# wait_for_ajax()
|
||||
#
|
||||
# def set_select(fieldname, value):
|
||||
# select = Select(find('select[data-fieldname="{0}"]'.format(fieldname))[0])
|
||||
# select.select_by_value(value)
|
||||
# wait_for_ajax()
|
||||
#
|
||||
#
|
||||
# def wait_for_page(name):
|
||||
# global cur_route
|
||||
# cur_route = None
|
||||
# route = '[data-page-route="{0}"]'.format(name)
|
||||
# wait_for_ajax()
|
||||
# elem = wait(route)
|
||||
# wait_for_ajax()
|
||||
# cur_route = route
|
||||
# return elem
|
||||
#
|
||||
#
|
||||
# def wait_till_visible(selector):
|
||||
# if cur_route:
|
||||
# selector = cur_route + " " + selector
|
||||
# return get_wait().until(EC.visibility_of_element_located((By.CSS_SELECTOR, selector)))
|
||||
#
|
||||
#
|
||||
# def wait_for_state(state):
|
||||
# return wait(cur_route + '[data-state="{0}"]'.format(state), True)
|
||||
#
|
||||
#
|
||||
|
|
@ -14,7 +14,6 @@ semantic_version
|
|||
rauth>=0.6.2
|
||||
requests
|
||||
redis==2.10.6
|
||||
selenium
|
||||
babel==2.6.0
|
||||
ipython
|
||||
html2text==2016.9.19
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue