- Fixes [Issue/15324](https://github.com/frappe/frappe/issues/15324) - When selecting a value for Link Field, the English text was set as link field value. - This PR aims to fix it by setting the translated text as link field value on selection. Todo: - [x] Show translated text in the select dropdown - [x] Set translated value to Link field on select - [x] Show original value when link field is in focus - [x] Add option to toggle this behaviour ### Behaviour - Link field loses focus: show the translated name. - Link field is focused - If old value is present - If options **are** one of [Role, DocType]: show the translated name - Else: show the name (untranslated) to enable search in untranslated values - Else: show what the user typed (untranslated) to enable search in untranslated values - Value is selected: link field loses focus ## Demo ### Link to UOM in a custom Item DocType The UOM names are in english, so the search needs to happen in english. When possible, the translation is displayed. #### Before https://user-images.githubusercontent.com/14891507/156415248-e5e80d05-53dc-4ca8-89c7-998986ff6e99.mov #### After https://user-images.githubusercontent.com/14891507/156410386-a874430c-f340-43ed-9c3a-92e8d4d50fc9.mov ### Link to DocType in Customize Form The DocType names get translated before being searched. This is a preexisting hack in the framework for DocType and Role. In this case, we can search in the translations. #### Before https://user-images.githubusercontent.com/14891507/156414648-8e505f8c-9dee-4358-8182-3b358c28bb62.mov #### After https://user-images.githubusercontent.com/14891507/156411881-c4ca22e1-1397-4e13-9768-5e16b72f8d6d.mov https://docs.erpnext.com/docs/v13/user/manual/en/customize-erpnext/customize-form/edit?wiki_page_patch=fdafee2715
389 lines
11 KiB
JavaScript
389 lines
11 KiB
JavaScript
context('Control Link', () => {
|
|
before(() => {
|
|
cy.login();
|
|
cy.visit('/app/website');
|
|
});
|
|
|
|
beforeEach(() => {
|
|
cy.visit('/app/website');
|
|
cy.create_records({
|
|
doctype: 'ToDo',
|
|
description: 'this is a test todo for link'
|
|
}).as('todos');
|
|
});
|
|
|
|
function get_dialog_with_link() {
|
|
return cy.dialog({
|
|
title: 'Link',
|
|
fields: [
|
|
{
|
|
'label': 'Select ToDo',
|
|
'fieldname': 'link',
|
|
'fieldtype': 'Link',
|
|
'options': 'ToDo',
|
|
}
|
|
]
|
|
});
|
|
}
|
|
|
|
function get_dialog_with_user_link() {
|
|
return cy.dialog({
|
|
title: 'Link',
|
|
fields: [
|
|
{
|
|
'label': 'Select User',
|
|
'fieldname': 'link',
|
|
'fieldtype': 'Link',
|
|
'options': 'User',
|
|
}
|
|
]
|
|
});
|
|
}
|
|
|
|
it('should set the valid value', () => {
|
|
get_dialog_with_link().as('dialog');
|
|
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype": "Property Setter",
|
|
"doc_type": "User",
|
|
"property": "translate_link_fields",
|
|
"property_type": "Check",
|
|
"doctype_or_field": "DocType",
|
|
"value": "0"
|
|
}, true);
|
|
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype": "Property Setter",
|
|
"doc_type": "ToDo",
|
|
"property": "show_title_field_in_link",
|
|
"property_type": "Check",
|
|
"doctype_or_field": "DocType",
|
|
"value": "0"
|
|
}, true);
|
|
|
|
cy.intercept('POST', '/api/method/frappe.desk.search.search_link').as('search_link');
|
|
|
|
cy.get('.frappe-control[data-fieldname=link] input').focus().as('input');
|
|
cy.wait('@search_link');
|
|
cy.get('@input').type('todo for link', { delay: 200 });
|
|
cy.wait('@search_link');
|
|
cy.get('.frappe-control[data-fieldname=link]').findByRole('listbox').should('be.visible');
|
|
cy.get('.frappe-control[data-fieldname=link] input').type('{enter}', { delay: 100 });
|
|
cy.get('.frappe-control[data-fieldname=link] input').blur();
|
|
cy.get('@dialog').then(dialog => {
|
|
cy.get('@todos').then(todos => {
|
|
let value = dialog.get_value('link');
|
|
expect(value).to.eq(todos[0]);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should unset invalid value', () => {
|
|
get_dialog_with_link().as('dialog');
|
|
|
|
cy.intercept('POST', '/api/method/frappe.client.validate_link').as('validate_link');
|
|
|
|
cy.get('.frappe-control[data-fieldname=link] input')
|
|
.type('invalid value', { delay: 100 })
|
|
.blur();
|
|
cy.wait('@validate_link');
|
|
cy.get('.frappe-control[data-fieldname=link] input').should('have.value', '');
|
|
});
|
|
|
|
it("should be possible set empty value explicitly", () => {
|
|
get_dialog_with_link().as("dialog");
|
|
|
|
cy.intercept("POST", "/api/method/frappe.client.validate_link").as("validate_link");
|
|
|
|
cy.get(".frappe-control[data-fieldname=link] input")
|
|
.type(" ", { delay: 100 })
|
|
.blur();
|
|
cy.wait("@validate_link");
|
|
cy.get(".frappe-control[data-fieldname=link] input").should("have.value", "");
|
|
cy.window()
|
|
.its("cur_dialog")
|
|
.then((dialog) => {
|
|
expect(dialog.get_value("link")).to.equal('');
|
|
});
|
|
});
|
|
|
|
it('should route to form on arrow click', () => {
|
|
get_dialog_with_link().as('dialog');
|
|
|
|
cy.intercept('POST', '/api/method/frappe.client.validate_link').as('validate_link');
|
|
cy.intercept('POST', '/api/method/frappe.desk.search.search_link').as('search_link');
|
|
|
|
cy.get('@todos').then(todos => {
|
|
cy.get('.frappe-control[data-fieldname=link] input').as('input');
|
|
cy.get('@input').focus();
|
|
cy.wait('@search_link');
|
|
cy.get('@input').type(todos[0]).blur();
|
|
cy.wait('@validate_link');
|
|
cy.get('@input').focus();
|
|
cy.wait(500); // wait for arrow to show
|
|
cy.get('.frappe-control[data-fieldname=link] .btn-open')
|
|
.should('be.visible')
|
|
.click();
|
|
cy.location('pathname').should('eq', `/app/todo/${todos[0]}`);
|
|
});
|
|
});
|
|
|
|
it('show title field in link', () => {
|
|
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype": "Property Setter",
|
|
"doc_type": "User",
|
|
"property": "translate_link_fields",
|
|
"property_type": "Check",
|
|
"doctype_or_field": "DocType",
|
|
"value": "0"
|
|
}, true);
|
|
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype": "Property Setter",
|
|
"doc_type": "ToDo",
|
|
"property": "show_title_field_in_link",
|
|
"property_type": "Check",
|
|
"doctype_or_field": "DocType",
|
|
"value": "1"
|
|
}, true);
|
|
|
|
cy.clear_cache();
|
|
cy.wait(500);
|
|
|
|
get_dialog_with_link().as('dialog');
|
|
cy.window().its('frappe').then(frappe => {
|
|
if (!frappe.boot) {
|
|
frappe.boot = {
|
|
link_title_doctypes: ['ToDo']
|
|
};
|
|
} else {
|
|
frappe.boot.link_title_doctypes = ['ToDo'];
|
|
}
|
|
});
|
|
|
|
cy.intercept('POST', '/api/method/frappe.desk.search.search_link').as('search_link');
|
|
|
|
cy.get('.frappe-control[data-fieldname=link] input').focus().as('input');
|
|
cy.wait('@search_link');
|
|
cy.get('@input').type('todo for link');
|
|
cy.wait('@search_link');
|
|
cy.get('.frappe-control[data-fieldname=link] ul').should('be.visible');
|
|
cy.get('.frappe-control[data-fieldname=link] input').type('{enter}', { delay: 100 });
|
|
cy.get('.frappe-control[data-fieldname=link] input').blur();
|
|
cy.get('@dialog').then(dialog => {
|
|
cy.get('@todos').then(todos => {
|
|
let field = dialog.get_field('link');
|
|
let value = field.get_value();
|
|
let label = field.get_label_value();
|
|
|
|
expect(value).to.eq(todos[0]);
|
|
expect(label).to.eq('this is a test todo for link');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should update dependant fields (via fetch_from)', () => {
|
|
cy.get('@todos').then(todos => {
|
|
cy.visit(`/app/todo/${todos[0]}`);
|
|
cy.intercept('POST', '/api/method/frappe.desk.search.search_link').as('search_link');
|
|
cy.intercept('POST', '/api/method/frappe.client.validate_link').as('validate_link');
|
|
|
|
cy.get('.frappe-control[data-fieldname=assigned_by] input').focus().as('input');
|
|
cy.get('@input').type('Administrator', {delay: 100}).blur();
|
|
cy.wait('@validate_link');
|
|
cy.get('.frappe-control[data-fieldname=assigned_by_full_name] .control-value').should(
|
|
'contain', 'Administrator'
|
|
);
|
|
|
|
cy.window()
|
|
.its("cur_frm.doc.assigned_by")
|
|
.should("eq", "Administrator");
|
|
|
|
// invalid input
|
|
cy.get('@input').clear().type('invalid input', {delay: 100}).blur();
|
|
cy.get('.frappe-control[data-fieldname=assigned_by_full_name] .control-value').should(
|
|
'contain', ''
|
|
);
|
|
|
|
cy.window()
|
|
.its("cur_frm.doc.assigned_by")
|
|
.should("eq", null);
|
|
|
|
// set valid value again
|
|
cy.get('@input').clear().focus();
|
|
cy.wait('@search_link');
|
|
cy.get('@input').type('Administrator', {delay: 100}).blur();
|
|
cy.wait('@validate_link');
|
|
|
|
cy.window()
|
|
.its("cur_frm.doc.assigned_by")
|
|
.should("eq", "Administrator");
|
|
|
|
// clear input
|
|
cy.get('@input').clear().blur();
|
|
cy.get('.frappe-control[data-fieldname=assigned_by_full_name] .control-value').should(
|
|
'contain', ''
|
|
);
|
|
|
|
cy.window()
|
|
.its("cur_frm.doc.assigned_by")
|
|
.should("eq", "");
|
|
});
|
|
});
|
|
|
|
it("should set default values", () => {
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype_or_field": "DocField",
|
|
"doc_type": "ToDo",
|
|
"field_name": "assigned_by",
|
|
"property": "default",
|
|
"property_type": "Text",
|
|
"value": "Administrator"
|
|
}, true);
|
|
cy.reload();
|
|
cy.new_form("ToDo");
|
|
cy.fill_field("description", "new", "Text Editor");
|
|
cy.intercept("POST", "/api/method/frappe.desk.form.save.savedocs").as("save_form");
|
|
cy.findByRole("button", {name: "Save"}).click();
|
|
cy.wait("@save_form");
|
|
cy.get(".frappe-control[data-fieldname=assigned_by_full_name] .control-value").should(
|
|
"contain", "Administrator"
|
|
);
|
|
// if user clears default value explicitly, system should not reset default again
|
|
cy.get_field("assigned_by").clear().blur();
|
|
cy.intercept("POST", "/api/method/frappe.desk.form.save.savedocs").as("save_form");
|
|
cy.findByRole("button", {name: "Save"}).click();
|
|
cy.wait("@save_form");
|
|
cy.get_field("assigned_by").should("have.value", "");
|
|
cy.get(".frappe-control[data-fieldname=assigned_by_full_name] .control-value").should(
|
|
"contain", ""
|
|
);
|
|
});
|
|
|
|
it('show translated text for link with show_title_field_in_link enabled', () => {
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype": "Property Setter",
|
|
"doc_type": "ToDo",
|
|
"property": "translate_link_fields",
|
|
"property_type": "Check",
|
|
"doctype_or_field": "DocType",
|
|
"value": "1"
|
|
}, true);
|
|
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype": "Property Setter",
|
|
"doc_type": "ToDo",
|
|
"property": "show_title_field_in_link",
|
|
"property_type": "Check",
|
|
"doctype_or_field": "DocType",
|
|
"value": "1"
|
|
}, true);
|
|
|
|
cy.window().its('frappe').then(frappe => {
|
|
cy.insert_doc("Translation", {
|
|
doctype: "Translation",
|
|
language: frappe.boot.lang,
|
|
source_text: "this is a test todo for link",
|
|
translated_text: "this is a translated test todo for link",
|
|
});
|
|
});
|
|
|
|
cy.clear_cache();
|
|
cy.wait(500);
|
|
|
|
cy.window().its('frappe').then(frappe => {
|
|
if (!frappe.boot) {
|
|
frappe.boot = {
|
|
link_title_doctypes: ['ToDo'],
|
|
translatable_doctypes: ['ToDo']
|
|
};
|
|
} else {
|
|
frappe.boot.link_title_doctypes = ['ToDo'];
|
|
frappe.boot.translatable_doctypes = ['ToDo'];
|
|
}
|
|
});
|
|
|
|
get_dialog_with_link().as('dialog');
|
|
cy.intercept('POST', '/api/method/frappe.desk.search.search_link').as('search_link');
|
|
|
|
cy.get('.frappe-control[data-fieldname=link] input').focus().as('input');
|
|
cy.wait('@search_link');
|
|
cy.get('@input').type('todo for link', { delay: 100 });
|
|
cy.wait('@search_link');
|
|
cy.get('.frappe-control[data-fieldname=link] ul').should('be.visible');
|
|
cy.get('.frappe-control[data-fieldname=link] input').type('{enter}', { delay: 100 });
|
|
cy.get('.frappe-control[data-fieldname=link] input').blur();
|
|
cy.get('@dialog').then(dialog => {
|
|
cy.get('@todos').then(todos => {
|
|
let field = dialog.get_field('link');
|
|
let value = field.get_value();
|
|
let label = field.get_label_value();
|
|
|
|
expect(value).to.eq(todos[0]);
|
|
expect(label).to.eq('this is a translated test todo for link');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('show translated text for link with show_title_field_in_link disabled', () => {
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype": "Property Setter",
|
|
"doc_type": "User",
|
|
"property": "translate_link_fields",
|
|
"property_type": "Check",
|
|
"doctype_or_field": "DocType",
|
|
"value": "1"
|
|
}, true);
|
|
|
|
cy.insert_doc("Property Setter", {
|
|
"doctype": "Property Setter",
|
|
"doc_type": "ToDo",
|
|
"property": "show_title_field_in_link",
|
|
"property_type": "Check",
|
|
"doctype_or_field": "DocType",
|
|
"value": "0"
|
|
}, true);
|
|
|
|
cy.window().its('frappe').then(frappe => {
|
|
cy.insert_doc("Translation", {
|
|
doctype: "Translation",
|
|
language: frappe.boot.lang,
|
|
source_text: "test@erpnext.com",
|
|
translated_text: "translatedtest@erpnext.com",
|
|
});
|
|
});
|
|
|
|
cy.clear_cache();
|
|
cy.wait(500);
|
|
|
|
cy.window().its('frappe').then(frappe => {
|
|
if (!frappe.boot) {
|
|
frappe.boot = {
|
|
translatable_doctypes: ['User']
|
|
};
|
|
} else {
|
|
frappe.boot.translatable_doctypes = ['User'];
|
|
}
|
|
});
|
|
|
|
get_dialog_with_user_link().as('dialog');
|
|
cy.intercept('POST', '/api/method/frappe.desk.search.search_link').as('search_link');
|
|
|
|
cy.get('.frappe-control[data-fieldname=link] input').focus().as('input');
|
|
cy.wait('@search_link');
|
|
cy.get('@input').type('test@erpnext.com', { delay: 100 });
|
|
cy.wait('@search_link');
|
|
cy.get('.frappe-control[data-fieldname=link] ul').should('be.visible');
|
|
cy.get('.frappe-control[data-fieldname=link] input').type('{enter}', { delay: 100 });
|
|
cy.get('.frappe-control[data-fieldname=link] input').blur();
|
|
cy.get('@dialog').then(dialog => {
|
|
let field = dialog.get_field('link');
|
|
let value = field.get_value();
|
|
let label = field.get_label_value();
|
|
|
|
expect(value).to.eq('test@erpnext.com');
|
|
expect(label).to.eq('translatedtest@erpnext.com');
|
|
});
|
|
});
|
|
});
|