diff --git a/cypress/integration/form.js b/cypress/integration/form.js index 99a4336bcb..4d50a5f66a 100644 --- a/cypress/integration/form.js +++ b/cypress/integration/form.js @@ -78,4 +78,20 @@ context('Form', () => { cy.get('@row2').click(); cy.get('@email_input2').should('not.have.class', 'invalid'); }); + + it('Shows version conflict warning', { scrollBehavior: false }, () => { + cy.visit('/app/todo'); + + cy.insert_doc("ToDo", {"description": "old"}).then(doc => { + cy.visit(`/app/todo/${doc.name}`); + // make form dirty + cy.fill_field("status", "Cancelled", "Select"); + + // update doc using api - simulating parallel change by another user + cy.update_doc("ToDo", doc.name, {"status": "Closed"}).then(() => { + cy.findByRole("button", {name: "Refresh"}).click(); + cy.get_field("status", "Select").should("have.value", "Closed"); + }) + }) + }); }); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index b3708a1dba..5ee26348e2 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -291,7 +291,11 @@ Cypress.Commands.add('clear_datepickers', () => { cy.get('.datepicker').should('not.exist'); }); + Cypress.Commands.add('insert_doc', (doctype, args, ignore_duplicate) => { + if (!args.doctype) { + args.doctype = doctype; + } return cy .window() .its('frappe.csrf_token') @@ -324,6 +328,30 @@ Cypress.Commands.add('insert_doc', (doctype, args, ignore_duplicate) => { }); }); +Cypress.Commands.add('update_doc', (doctype, docname, args) => { + return cy + .window() + .its('frappe.csrf_token') + .then(csrf_token => { + return cy + .request({ + method: 'PUT', + url: `/api/resource/${doctype}/${docname}`, + body: args, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + 'X-Frappe-CSRF-Token': csrf_token + }, + }) + .then(res => { + expect(res.status).to.eq(200); + return res.body.data; + }); + }); +}); + + Cypress.Commands.add('open_list_filter', () => { cy.get('.filter-section .filter-button').click(); cy.wait(300); diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index 13d61d689b..148ec7ca86 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -506,8 +506,6 @@ frappe.ui.form.Form = class FrappeForm { } initialize_new_doc() { - // moved this call to refresh function - // this.check_doctype_conflict(docname); var me = this; // hide any open grid @@ -1024,8 +1022,8 @@ frappe.ui.form.Form = class FrappeForm { if(this.doc.__unsaved) { this.dashboard.clear_headline(); this.dashboard.set_headline_alert(__("This form has been modified after you have loaded it") - + '' - + __("Refresh") + '', "alert-warning"); + + '', "alert-warning"); } else { this.reload_doc(); } diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index 4b6ee31b71..32ba1d89c2 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -54,7 +54,7 @@ $.extend(frappe.model, { if(frappe.get_route()[0]==="Form" && cur_frm.doc.doctype===doc.doctype && cur_frm.doc.name===doc.name) { if(!frappe.ui.form.is_saving && data.modified!=cur_frm.doc.modified) { doc.__needs_refresh = true; - cur_frm.check_doctype_conflict(); + cur_frm.show_conflict_message(); } } else { if(!doc.__unsaved) {