Merge branch 'master' into develop
diff --git a/.travis.yml b/.travis.yml
index 0d8d2ff..0b3b49f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -53,4 +53,4 @@
   - set -e
   - bench --verbose run-tests
   - sleep 5
-  - bench --verbose run-tests --ui-tests
+  - bench --verbose run-ui-tests --app erpnext
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index fd32dd4..3524305 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -1,6 +1,8 @@
 # -*- coding: utf-8 -*-
 from __future__ import unicode_literals
+import inspect
 import frappe
+from erpnext.hooks import regional_overrides
 
 __version__ = '8.4.3'
 
@@ -65,3 +67,34 @@
 			company, "enable_perpetual_inventory") or 0
 
 	return frappe.local.enable_perpetual_inventory[company]
+
+def get_region(company=None):
+	'''Return the default country based on flag, company or global settings
+
+	You can also set global company flag in `frappe.flags.company`
+	'''
+	if company or frappe.flags.company:
+		return frappe.db.get_value('Company',
+			company or frappe.flags.company, 'country')
+	elif frappe.flags.country:
+		return frappe.flags.country
+	else:
+		return frappe.get_system_settings('country')
+
+def allow_regional(fn):
+	'''Decorator to make a function regionally overridable
+
+	Example:
+	@erpnext.allow_regional
+	def myfunction():
+	  pass'''
+	def caller(*args, **kwargs):
+		region = get_region()
+		fn_name = inspect.getmodule(fn).__name__ + '.' + fn.__name__
+		if region in regional_overrides and fn_name in regional_overrides[region]:
+			return frappe.get_attr(regional_overrides[region][fn_name])(*args, **kwargs)
+		else:
+			return fn(*args, **kwargs)
+
+	return caller
+
diff --git a/erpnext/accounts/doctype/account/account.js b/erpnext/accounts/doctype/account/account.js
index 8a9a439..ed7e39a 100644
--- a/erpnext/accounts/doctype/account/account.js
+++ b/erpnext/accounts/doctype/account/account.js
@@ -1,94 +1,94 @@
-// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
-
-cur_frm.cscript.refresh = function (doc, cdt, cdn) {
-	if (doc.__islocal) {
-		frappe.msgprint(__("Please create new account from Chart of Accounts."));
-		throw "cannot create";
-	}
-
-	cur_frm.toggle_display('account_name', doc.__islocal);
-
-	// hide fields if group
-	cur_frm.toggle_display(['account_type', 'tax_rate'], cint(doc.is_group) == 0)
-
-	// disable fields
-	cur_frm.toggle_enable(['account_name', 'is_group', 'company'], false);
-
-	if (cint(doc.is_group) == 0) {
-		cur_frm.toggle_display('freeze_account', doc.__onload && doc.__onload.can_freeze_account);
-	}
-
-	// read-only for root accounts
-	if (!doc.parent_account) {
-		cur_frm.set_read_only();
-		cur_frm.set_intro(__("This is a root account and cannot be edited."));
-	} else {
-		// credit days and type if customer or supplier
-		cur_frm.set_intro(null);
-
-		cur_frm.cscript.account_type(doc, cdt, cdn);
-
-		// show / hide convert buttons
-		cur_frm.cscript.add_toolbar_buttons(doc);
-	}
-}
-
-cur_frm.add_fetch('parent_account', 'report_type', 'report_type');
-cur_frm.add_fetch('parent_account', 'root_type', 'root_type');
-
-cur_frm.cscript.account_type = function (doc, cdt, cdn) {
-	if (doc.is_group == 0) {
-		cur_frm.toggle_display(['tax_rate'], doc.account_type == 'Tax');
-		cur_frm.toggle_display('warehouse', doc.account_type == 'Stock');
-	}
-}
-
-cur_frm.cscript.add_toolbar_buttons = function (doc) {
-	cur_frm.add_custom_button(__('Chart of Accounts'),
-		function () { frappe.set_route("Tree", "Account"); });
-
-	if (doc.is_group == 1) {
-		cur_frm.add_custom_button(__('Group to Non-Group'),
-			function () { cur_frm.cscript.convert_to_ledger(); }, 'fa fa-retweet', 'btn-default');
-	} else if (cint(doc.is_group) == 0) {
-		cur_frm.add_custom_button(__('Ledger'), function () {
-			frappe.route_options = {
-				"account": doc.name,
-				"from_date": frappe.sys_defaults.year_start_date,
-				"to_date": frappe.sys_defaults.year_end_date,
-				"company": doc.company
+frappe.ui.form.on('Account', {
+	setup: function(frm) {
+		frm.add_fetch('parent_account', 'report_type', 'report_type');
+		frm.add_fetch('parent_account', 'root_type', 'root_type');
+	},
+	onload: function(frm) {
+		frm.set_query('parent_account', function(doc) {
+			return {
+				filters: {
+					"is_group": 1,
+					"company": doc.company
+				}
 			};
-			frappe.set_route("query-report", "General Ledger");
 		});
+	},
+	refresh: function(frm) {
+		if (frm.doc.__islocal) {
+			frappe.msgprint(__("Please create new account from Chart of Accounts."));
+			throw "cannot create";
+		}
 
-		cur_frm.add_custom_button(__('Non-Group to Group'),
-			function () { cur_frm.cscript.convert_to_group(); }, 'fa fa-retweet', 'btn-default')
+		frm.toggle_display('account_name', frm.doc.__islocal);
+
+		// hide fields if group
+		frm.toggle_display(['account_type', 'tax_rate'], cint(frm.doc.is_group) == 0);
+
+		// disable fields
+		frm.toggle_enable(['account_name', 'is_group', 'company'], false);
+
+		if (cint(frm.doc.is_group) == 0) {
+			frm.toggle_display('freeze_account', frm.doc.__onload
+				&& frm.doc.__onload.can_freeze_account);
+		}
+
+		// read-only for root accounts
+		if (!frm.doc.parent_account) {
+			frm.set_read_only();
+			frm.set_intro(__("This is a root account and cannot be edited."));
+		} else {
+			// credit days and type if customer or supplier
+			frm.set_intro(null);
+			frm.trigger('account_type');
+
+			// show / hide convert buttons
+			frm.trigger('add_toolbar_buttons');
+		}
+	},
+	account_type: function (frm) {
+		if (frm.doc.is_group == 0) {
+			frm.toggle_display(['tax_rate'], frm.doc.account_type == 'Tax');
+			frm.toggle_display('warehouse', frm.doc.account_type == 'Stock');
+		}
+	},
+	add_toolbar_buttons: function(frm) {
+		frm.add_custom_button(__('Chart of Accounts'),
+			function () { frappe.set_route("Tree", "Account"); });
+
+		if (frm.doc.is_group == 1) {
+			frm.add_custom_button(__('Group to Non-Group'), function () {
+				return frappe.call({
+					doc: frm.doc,
+					method: 'convert_group_to_ledger',
+					callback: function() {
+						frm.refresh();
+					}
+				});
+			});
+		} else if (cint(frm.doc.is_group) == 0) {
+			cur_frm.add_custom_button(__('Ledger'), function () {
+				frappe.route_options = {
+					"account": frm.doc.name,
+					"from_date": frappe.sys_defaults.year_start_date,
+					"to_date": frappe.sys_defaults.year_end_date,
+					"company": frm.doc.company
+				};
+				frappe.set_route("query-report", "General Ledger");
+			});
+
+			frm.add_custom_button(__('Non-Group to Group'), function () {
+				return frappe.call({
+					doc: frm.doc,
+					method: 'convert_ledger_to_group',
+					callback: function() {
+						frm.refresh();
+					}
+				});
+			});
+		}
+
 	}
-}
-
-cur_frm.cscript.convert_to_ledger = function (doc, cdt, cdn) {
-	return $c_obj(cur_frm.doc, 'convert_group_to_ledger', '', function (r, rt) {
-		if (r.message == 1) {
-			cur_frm.refresh();
-		}
-	});
-}
-
-cur_frm.cscript.convert_to_group = function (doc, cdt, cdn) {
-	return $c_obj(cur_frm.doc, 'convert_ledger_to_group', '', function (r, rt) {
-		if (r.message == 1) {
-			cur_frm.refresh();
-		}
-	});
-}
-
-cur_frm.fields_dict['parent_account'].get_query = function (doc) {
-	return {
-		filters: {
-			"is_group": 1,
-			"company": doc.company
-		}
-	}
-}
+});
\ No newline at end of file
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 0966485..fedc6d5 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 from frappe import _
-from . import __version__ as app_version
 
 app_name = "erpnext"
 app_title = "ERPNext"
@@ -80,13 +79,7 @@
 			"parents": [{"title": _("Supplier Quotation"), "name": "quotations"}]
 		}
 	},
-	{"from_route": "/quotes", "to_route": "Quotation"},
-	{"from_route": "/quotes/<path:name>", "to_route": "order",
-		"defaults": {
-			"doctype": "Quotation",
-			"parents": [{"title": _("Quotes"), "name": "quotes"}]
-		}
-	},
+	{"from_route": "/quotation", "to_route": "Quotation"},
 	{"from_route": "/shipments", "to_route": "Delivery Note"},
 	{"from_route": "/shipments/<path:name>", "to_route": "order",
 		"defaults": {
@@ -117,7 +110,7 @@
 	{"title": _("Projects"), "route": "/project", "reference_doctype": "Project"},
 	{"title": _("Request for Quotations"), "route": "/rfq", "reference_doctype": "Request for Quotation", "role": "Supplier"},
 	{"title": _("Supplier Quotation"), "route": "/quotations", "reference_doctype": "Supplier Quotation", "role": "Supplier"},
-	{"title": _("Quotes"), "route": "/quotes", "reference_doctype": "Quotation", "role":"Customer"},
+	{"title": _("Quotations"), "route": "/quotation", "reference_doctype": "Quotation", "role":"Customer"},
 	{"title": _("Orders"), "route": "/orders", "reference_doctype": "Sales Order", "role":"Customer"},
 	{"title": _("Invoices"), "route": "/invoices", "reference_doctype": "Sales Invoice", "role":"Customer"},
 	{"title": _("Shipments"), "route": "/shipments", "reference_doctype": "Delivery Note", "role":"Customer"},
@@ -194,6 +187,8 @@
 	]
 }
 
+email_brand_image = "assets/erpnext/images/erpnext-logo.jpg"
+
 default_mail_footer = """<div style="text-align: center;">
 	<a href="https://erpnext.com?source=via_email_footer" target="_blank" style="color: #8d99a6;">
 		Sent via ERPNext
@@ -211,3 +206,9 @@
 get_site_info = 'erpnext.utilities.get_site_info'
 
 payment_gateway_enabled = "erpnext.accounts.utils.create_payment_gateway_account"
+
+regional_overrides = {
+	'India': {
+		'erpnext.tests.test_regional.test_method': 'erpnext.regional.india.utils.test_method'
+	}
+}
diff --git a/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py b/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py
index 7fff5f5..f03c6fa 100644
--- a/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py
+++ b/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py
@@ -8,7 +8,7 @@
 from frappe import _
 from email_reply_parser import EmailReplyParser
 from erpnext.hr.doctype.employee.employee import is_holiday
-from frappe.utils import formatdate
+from frappe.utils import global_date_format
 from markdown2 import markdown
 
 class DailyWorkSummary(Document):
@@ -24,17 +24,18 @@
 
 	def send_summary(self):
 		'''Send summary of all replies. Called at midnight'''
-		message = self.get_summary_message()
+		args = self.get_message_details()
 
 		frappe.sendmail(recipients = get_employee_emails(self.company, False),
-			message = message,
+			template='daily_work_summary',
+			args=args,
 			subject = _('Daily Work Summary for {0}').format(self.company),
 			reference_doctype=self.doctype, reference_name=self.name)
 
 		self.db_set('status', 'Sent')
 
-	def get_summary_message(self):
-		'''Return summary of replies as HTML'''
+	def get_message_details(self):
+		'''Return args for template'''
 		settings = frappe.get_doc('Daily Work Summary Settings')
 
 		replies = frappe.get_all('Communication', fields=['content', 'text_content', 'sender'],
@@ -45,8 +46,12 @@
 		did_not_reply = self.email_sent_to.split()
 
 		for d in replies:
-			d.sender_name = frappe.db.get_value("Employee", {"user_id": d.sender},
-				"employee_name") or d.sender
+			emp = frappe.db.get_values("Employee", {"user_id": d.sender},
+				["employee_name", "image"], as_dict=True)
+
+			d.sender_name = emp[0].employee_name if emp else d.sender
+			d.image = emp[0].image if emp and emp[0].image else None
+
 			if d.sender in did_not_reply:
 				did_not_reply.remove(d.sender)
 			if d.text_content:
@@ -56,30 +61,12 @@
 		did_not_reply = [(frappe.db.get_value("Employee", {"user_id": email}, "employee_name") or email)
 			for email in did_not_reply]
 
-		return frappe.render_template(self.get_summary_template(),
-			dict(replies=replies,
-				original_message=settings.message,
-				title=_('Daily Work Summary for {0}'.format(formatdate(self.creation))),
-				did_not_reply= ', '.join(did_not_reply) or '',
-				did_not_reply_title = _('No replies from')))
+		return dict(replies=replies,
+			original_message=settings.message,
+			title=_('Daily Work Summary for {0}'.format(global_date_format(self.creation))),
+			did_not_reply= ', '.join(did_not_reply) or '',
+			did_not_reply_title = _('No replies from'))
 
-	def get_summary_template(self):
-		return '''
-<h3>{{ title }}</h3>
-
-{% for reply in replies %}
-<h4>{{ reply.sender_name }}</h4>
-<p style="padding-bottom: 20px">
-	{{ reply.content }}
-</p>
-<hr>
-{% endfor %}
-
-{% if did_not_reply %}
-<p>{{ did_not_reply_title }}: {{ did_not_reply }}</p>
-{% endif %}
-
-'''
 
 def get_employee_emails(company, only_working=True):
 	'''Returns list of Employee user ids for the given company who are working today
diff --git a/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py b/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py
index ad9d43f..63e6fdf 100644
--- a/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py
+++ b/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py
@@ -46,9 +46,9 @@
 		daily_work_summary = frappe.get_doc('Daily Work Summary',
 			frappe.get_all('Daily Work Summary')[0].name)
 
-		summary = daily_work_summary.get_summary_message()
+		args = daily_work_summary.get_message_details()
 
-		self.assertTrue('I built Daily Work Summary!' in summary)
+		self.assertTrue('I built Daily Work Summary!' in args.get('replies')[0].content)
 
 	def setup_and_prepare_test(self, hour=None):
 		frappe.db.sql('delete from `tabDaily Work Summary`')
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 84e5f3e..437465a 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -22,3 +22,8 @@
 			if doc.gstin != "NA" and doc.gst_state_number != doc.gstin[:2]:
 				frappe.throw(_("First 2 digits of GSTIN should match with State number {0}")
 					.format(doc.gst_state_number))
+
+# don't remove this function it is used in tests
+def test_method():
+	'''test function'''
+	return 'overridden'
\ No newline at end of file
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index a4d4bf9..420b84a 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -93,7 +93,7 @@
 		'show_sidebar': True,
 		'show_search': True,
 		'no_breadcrumbs': True,
-		'title': _('Quotes'),
+		'title': _('Quotations'),
 	})
 
 	return list_context
diff --git a/erpnext/templates/emails/daily_work_summary.html b/erpnext/templates/emails/daily_work_summary.html
new file mode 100644
index 0000000..726de3b
--- /dev/null
+++ b/erpnext/templates/emails/daily_work_summary.html
@@ -0,0 +1,59 @@
+<table border="0" cellpadding="0" cellspacing="0" width="100%">
+	<tr>
+		<div style="color: #333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; word-wrap: break-word; overflow-wrap: break-word;">
+			<h3>{{ title }}</h3>
+		</div>
+	</tr>
+</table>
+{% for reply in replies %}
+<table border="0" cellpadding="0" cellspacing="0" width="100%"
+	style="background-color: #fafbfc; border: 1px solid #d1d8dd; border-radius: 3px 3px 0 0">
+	<tr height="10"></tr>
+	<tr>
+		<td width="15"></td>
+		<td valign="top" width="24">
+			{% if reply.image %}
+			<img width="24" height="24" embed="{{ reply.image }}" style="border-radius: 3px; vertical-align: middle;" />
+			{% else %}
+			<div style="width: 24px; height: 24px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;background: #fff; border-radius: 3px; border: 1px solid #d1d8dd; text-align: center; line-height: 24px; color: #d1d8dd;">
+				{{ reply.sender_name[0] }}
+			</div>
+			{% endif %}
+		</td>
+		<td width="10"></td>
+		<td>
+			<div style="font-size: 12px; color: #8D99A6; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; word-wrap: break-word; line-height: 22px; overflow-wrap: break-word; text-decoration: none;">
+				<span>{{ reply.sender_name }}</span>
+			</div>
+		</td>
+		<td width="15"></td>
+	</tr>
+	<tr height="10"></tr>
+</table>
+<table border="0" cellpadding="0" cellspacing="0" width="100%"
+	style="background-color: #fff; border: 1px solid #d1d8dd; border-top: none; border-radius: 0 0 3px 3px">
+	<tr height="10"></tr>
+	<tr>
+		<td width="15"></td>
+		<td>
+			<div style="font-size: 14px; color: #333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; word-wrap: break-word; line-height: 22px; overflow-wrap: break-word; text-decoration: none;">
+				{{ reply.content }}
+			</div>
+		</td>
+		<td width="15"></td>
+	</tr>
+	<tr height="10"></tr>
+</table>
+<table border="0" cellpadding="0" cellspacing="0" width="100%">
+	<tr height="20"></tr>
+</table>
+{% endfor %}
+{% if did_not_reply %}
+<table border="0" cellpadding="0" cellspacing="0" width="100%">
+	<tr>
+		<div style="font-size: 14px; color: #8D99A6; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; word-wrap: break-word; line-height: 22px; overflow-wrap: break-word; text-decoration: none;">
+			<p>{{ did_not_reply_title }}: {{ did_not_reply }}</p>
+		</div>
+	</tr>
+</table>
+{% endif %}
\ No newline at end of file
diff --git a/erpnext/templates/emails/daily_work_summary.txt b/erpnext/templates/emails/daily_work_summary.txt
new file mode 100644
index 0000000..2fb4380
--- /dev/null
+++ b/erpnext/templates/emails/daily_work_summary.txt
@@ -0,0 +1,11 @@
+{{ title }}
+
+{% for reply in replies %}
+{{ reply.sender_name }}:
+{{ reply.content }}
+
+
+{% endfor %}
+{% if did_not_reply %}
+{{ did_not_reply_title }}: {{ did_not_reply }}
+{% endif %}
\ No newline at end of file
diff --git a/erpnext/tests/test_regional.py b/erpnext/tests/test_regional.py
new file mode 100644
index 0000000..5d9628f
--- /dev/null
+++ b/erpnext/tests/test_regional.py
@@ -0,0 +1,13 @@
+import unittest, frappe, erpnext
+
+@erpnext.allow_regional
+def test_method():
+	return 'original'
+
+class TestInit(unittest.TestCase):
+	def test_regional_overrides(self):
+		frappe.flags.country = 'India'
+		self.assertEqual(test_method(), 'overridden')
+
+		frappe.flags.country = 'Nepal'
+		self.assertEqual(test_method(), 'original')
\ No newline at end of file
diff --git a/erpnext/tests/ui/accounts/test_account.js b/erpnext/tests/ui/accounts/test_account.js
new file mode 100644
index 0000000..6d7709b
--- /dev/null
+++ b/erpnext/tests/ui/accounts/test_account.js
@@ -0,0 +1,27 @@
+QUnit.module('accounts');
+
+QUnit.test("test account", function(assert) {
+	assert.expect(4);
+	let done = assert.async();
+	frappe.run_serially([
+		() => frappe.set_route('Tree', 'Account'),
+		() => frappe.tests.click_button('Expand All'),
+		() => frappe.tests.click_link('Debtors'),
+		() => frappe.tests.click_button('Edit'),
+		() => frappe.timeout(1),
+		() => {
+			assert.ok(cur_frm.doc.root_type=='Asset');
+			assert.ok(cur_frm.doc.report_type=='Balance Sheet');
+			assert.ok(cur_frm.doc.account_type=='Receivable');
+		},
+		() => frappe.tests.click_button('Ledger'),
+		() => frappe.timeout(1),
+		() => {
+			// check if general ledger report shown
+			assert.deepEqual(frappe.get_route(), ['query-report', 'General Ledger']);
+			window.history.back();
+			return frappe.timeout(1);
+		},
+		() => done()
+	]);
+});
diff --git a/erpnext/tests/ui/test_fixtures.js b/erpnext/tests/ui/data/test_fixtures.js
similarity index 100%
rename from erpnext/tests/ui/test_fixtures.js
rename to erpnext/tests/ui/data/test_fixtures.js
diff --git a/erpnext/tests/ui/selling/_test_lead.js b/erpnext/tests/ui/selling/_test_lead.js
new file mode 100644
index 0000000..2b895d9
--- /dev/null
+++ b/erpnext/tests/ui/selling/_test_lead.js
@@ -0,0 +1,18 @@
+QUnit.module("sales");
+
+QUnit.test("test: lead", function (assert) {
+	assert.expect(1);
+	let done = assert.async();
+	let random = frappe.utils.get_random(10);
+	frappe.run_serially([
+		() => frappe.tests.setup_doctype("Lead"),
+		() => frappe.set_route("List", "Lead"),
+		() => frappe.new_doc("Lead"),
+		() => cur_frm.set_value("lead_name", random),
+		() => cur_frm.save(),
+		() => {
+			assert.ok(cur_frm.doc.lead_name.includes(random));
+			return done();
+		}
+	]);
+});
diff --git a/erpnext/tests/ui/selling/_test_opportunity.js b/erpnext/tests/ui/selling/_test_opportunity.js
new file mode 100644
index 0000000..716a36e
--- /dev/null
+++ b/erpnext/tests/ui/selling/_test_opportunity.js
@@ -0,0 +1,19 @@
+QUnit.test("test: opportunity", function (assert) {
+	assert.expect(1);
+	let done = assert.async();
+	frappe.run_serially([
+		() => {
+			return frappe.tests.make("Opportunity", [{
+				enquiry_from: "Lead"
+			},
+			{
+				lead: "LEAD-00002"
+			}
+			]);
+		},
+		() => {
+			assert.ok(cur_frm.doc.lead === "LEAD-00002");
+			return done();
+		}
+	]);
+});
diff --git a/erpnext/tests/ui/test_sellling.js b/erpnext/tests/ui/selling/_test_quotation.js
similarity index 79%
rename from erpnext/tests/ui/test_sellling.js
rename to erpnext/tests/ui/selling/_test_quotation.js
index f676152..62dd05d 100644
--- a/erpnext/tests/ui/test_sellling.js
+++ b/erpnext/tests/ui/selling/_test_quotation.js
@@ -1,42 +1,3 @@
-QUnit.module("sales");
-
-QUnit.test("test: lead", function (assert) {
-	assert.expect(1);
-	let done = assert.async();
-	let random = frappe.utils.get_random(10);
-	frappe.run_serially([
-		() => frappe.tests.setup_doctype("Lead"),
-		() => frappe.set_route("List", "Lead"),
-		() => frappe.new_doc("Lead"),
-		() => cur_frm.set_value("lead_name", random),
-		() => cur_frm.save(),
-		() => {
-			assert.ok(cur_frm.doc.lead_name.includes(random));
-			return done();
-		}
-	]);
-});
-
-QUnit.test("test: opportunity", function (assert) {
-	assert.expect(1);
-	let done = assert.async();
-	frappe.run_serially([
-		() => {
-			return frappe.tests.make("Opportunity", [{
-				enquiry_from: "Lead"
-			},
-			{
-				lead: "LEAD-00002"
-			}
-			]);
-		},
-		() => {
-			assert.ok(cur_frm.doc.lead === "LEAD-00002");
-			return done();
-		}
-	]);
-});
-
 QUnit.test("test: quotation", function (assert) {
 	assert.expect(18);
 	let done = assert.async();