You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

328 line
8.2 KiB

  1. import 'cypress-file-upload';
  2. // ***********************************************
  3. // This example commands.js shows you how to
  4. // create various custom commands and overwrite
  5. // existing commands.
  6. //
  7. // For more comprehensive examples of custom
  8. // commands please read more here:
  9. // https://on.cypress.io/custom-commands
  10. // ***********************************************
  11. //
  12. //
  13. // -- This is a parent command --
  14. // Cypress.Commands.add("login", (email, password) => { ... });
  15. //
  16. //
  17. // -- This is a child command --
  18. // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... });
  19. //
  20. //
  21. // -- This is a dual command --
  22. // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... });
  23. //
  24. //
  25. // -- This is will overwrite an existing command --
  26. // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... });
  27. Cypress.Commands.add('login', (email, password) => {
  28. if (!email) {
  29. email = 'Administrator';
  30. }
  31. if (!password) {
  32. password = Cypress.config('adminPassword');
  33. }
  34. cy.request({
  35. url: '/api/method/login',
  36. method: 'POST',
  37. body: {
  38. usr: email,
  39. pwd: password
  40. }
  41. });
  42. });
  43. Cypress.Commands.add('call', (method, args) => {
  44. return cy
  45. .window()
  46. .its('frappe.csrf_token')
  47. .then(csrf_token => {
  48. return cy
  49. .request({
  50. url: `/api/method/${method}`,
  51. method: 'POST',
  52. body: args,
  53. headers: {
  54. Accept: 'application/json',
  55. 'Content-Type': 'application/json',
  56. 'X-Frappe-CSRF-Token': csrf_token
  57. }
  58. })
  59. .then(res => {
  60. expect(res.status).eq(200);
  61. return res.body;
  62. });
  63. });
  64. });
  65. Cypress.Commands.add('get_list', (doctype, fields = [], filters = []) => {
  66. filters = JSON.stringify(filters);
  67. fields = JSON.stringify(fields);
  68. let url = `/api/resource/${doctype}?fields=${fields}&filters=${filters}`;
  69. return cy
  70. .window()
  71. .its('frappe.csrf_token')
  72. .then(csrf_token => {
  73. return cy
  74. .request({
  75. method: 'GET',
  76. url,
  77. headers: {
  78. Accept: 'application/json',
  79. 'X-Frappe-CSRF-Token': csrf_token
  80. }
  81. })
  82. .then(res => {
  83. expect(res.status).eq(200);
  84. return res.body;
  85. });
  86. });
  87. });
  88. Cypress.Commands.add('get_doc', (doctype, name) => {
  89. return cy
  90. .window()
  91. .its('frappe.csrf_token')
  92. .then(csrf_token => {
  93. return cy
  94. .request({
  95. method: 'GET',
  96. url: `/api/resource/${doctype}/${name}`,
  97. headers: {
  98. Accept: 'application/json',
  99. 'X-Frappe-CSRF-Token': csrf_token
  100. }
  101. })
  102. .then(res => {
  103. expect(res.status).eq(200);
  104. return res.body;
  105. });
  106. });
  107. });
  108. Cypress.Commands.add('insert_doc', (doctype, args, ignore_duplicate) => {
  109. return cy
  110. .window()
  111. .its('frappe.csrf_token')
  112. .then(csrf_token => {
  113. return cy
  114. .request({
  115. method: 'POST',
  116. url: `/api/resource/${doctype}`,
  117. body: args,
  118. headers: {
  119. Accept: 'application/json',
  120. 'Content-Type': 'application/json',
  121. 'X-Frappe-CSRF-Token': csrf_token
  122. },
  123. failOnStatusCode: !ignore_duplicate
  124. })
  125. .then(res => {
  126. let status_codes = [200];
  127. if (ignore_duplicate) {
  128. status_codes.push(409);
  129. }
  130. expect(res.status).to.be.oneOf(status_codes);
  131. return res.body;
  132. });
  133. });
  134. });
  135. Cypress.Commands.add('remove_doc', (doctype, name) => {
  136. return cy
  137. .window()
  138. .its('frappe.csrf_token')
  139. .then(csrf_token => {
  140. return cy
  141. .request({
  142. method: 'DELETE',
  143. url: `/api/resource/${doctype}/${name}`,
  144. headers: {
  145. Accept: 'application/json',
  146. 'X-Frappe-CSRF-Token': csrf_token
  147. }
  148. })
  149. .then(res => {
  150. expect(res.status).eq(202);
  151. return res.body;
  152. });
  153. });
  154. });
  155. Cypress.Commands.add('create_records', doc => {
  156. return cy
  157. .call('frappe.tests.ui_test_helpers.create_if_not_exists', {doc})
  158. .then(r => r.message);
  159. });
  160. Cypress.Commands.add('set_value', (doctype, name, obj) => {
  161. return cy.call('frappe.client.set_value', {
  162. doctype,
  163. name,
  164. fieldname: obj
  165. });
  166. });
  167. Cypress.Commands.add('fill_field', (fieldname, value, fieldtype = 'Data') => {
  168. cy.get_field(fieldname, fieldtype).as('input');
  169. if (['Date', 'Time', 'Datetime'].includes(fieldtype)) {
  170. cy.get('@input').click().wait(200);
  171. cy.get('.datepickers-container .datepicker.active').should('exist');
  172. }
  173. if (fieldtype === 'Time') {
  174. cy.get('@input').clear().wait(200);
  175. }
  176. if (fieldtype === 'Select') {
  177. cy.get('@input').select(value);
  178. } else {
  179. cy.get('@input').type(value, {waitForAnimations: false, force: true});
  180. }
  181. return cy.get('@input');
  182. });
  183. Cypress.Commands.add('get_field', (fieldname, fieldtype = 'Data') => {
  184. let selector = `.form-control[data-fieldname="${fieldname}"]`;
  185. if (fieldtype === 'Text Editor') {
  186. selector = `[data-fieldname="${fieldname}"] .ql-editor[contenteditable=true]`;
  187. }
  188. if (fieldtype === 'Code') {
  189. selector = `[data-fieldname="${fieldname}"] .ace_text-input`;
  190. }
  191. return cy.get(selector);
  192. });
  193. Cypress.Commands.add('fill_table_field', (tablefieldname, row_idx, fieldname, value, fieldtype = 'Data') => {
  194. cy.get_table_field(tablefieldname, row_idx, fieldname, fieldtype).as('input');
  195. if (['Date', 'Time', 'Datetime'].includes(fieldtype)) {
  196. cy.get('@input').click().wait(200);
  197. cy.get('.datepickers-container .datepicker.active').should('exist');
  198. }
  199. if (fieldtype === 'Time') {
  200. cy.get('@input').clear().wait(200);
  201. }
  202. if (fieldtype === 'Select') {
  203. cy.get('@input').select(value);
  204. } else {
  205. cy.get('@input').type(value, {waitForAnimations: false, force: true});
  206. }
  207. return cy.get('@input');
  208. });
  209. Cypress.Commands.add('get_table_field', (tablefieldname, row_idx, fieldname, fieldtype = 'Data') => {
  210. let selector = `.frappe-control[data-fieldname="${tablefieldname}"]`;
  211. selector += ` [data-idx="${row_idx}"]`;
  212. selector += ` .form-in-grid`;
  213. if (fieldtype === 'Text Editor') {
  214. selector += ` [data-fieldname="${fieldname}"] .ql-editor[contenteditable=true]`;
  215. } else if (fieldtype === 'Code') {
  216. selector += ` [data-fieldname="${fieldname}"] .ace_text-input`;
  217. } else {
  218. selector += ` .form-control[data-fieldname="${fieldname}"]`;
  219. }
  220. return cy.get(selector);
  221. });
  222. Cypress.Commands.add('awesomebar', text => {
  223. cy.get('#navbar-search').type(`${text}{downarrow}{enter}`, {delay: 100});
  224. });
  225. Cypress.Commands.add('new_form', doctype => {
  226. let dt_in_route = doctype.toLowerCase().replace(/ /g, '-');
  227. cy.visit(`/app/${dt_in_route}/new`);
  228. cy.get('body').should('have.attr', 'data-route', `Form/${doctype}/new-${dt_in_route}-1`);
  229. cy.get('body').should('have.attr', 'data-ajax-state', 'complete');
  230. });
  231. Cypress.Commands.add('go_to_list', doctype => {
  232. cy.visit(`/app/list/${doctype}/list`);
  233. });
  234. Cypress.Commands.add('clear_cache', () => {
  235. cy.window()
  236. .its('frappe')
  237. .then(frappe => {
  238. frappe.ui.toolbar.clear_cache();
  239. });
  240. });
  241. Cypress.Commands.add('dialog', opts => {
  242. return cy.window().then(win => {
  243. var d = new win.frappe.ui.Dialog(opts);
  244. d.show();
  245. return d;
  246. });
  247. });
  248. Cypress.Commands.add('get_open_dialog', () => {
  249. return cy.get('.modal:visible').last();
  250. });
  251. Cypress.Commands.add('hide_dialog', () => {
  252. cy.wait(200);
  253. cy.get_open_dialog().find('.btn-modal-close').click();
  254. cy.get('.modal:visible').should('not.exist');
  255. });
  256. Cypress.Commands.add('insert_doc', (doctype, args, ignore_duplicate) => {
  257. return cy
  258. .window()
  259. .its('frappe.csrf_token')
  260. .then(csrf_token => {
  261. return cy
  262. .request({
  263. method: 'POST',
  264. url: `/api/resource/${doctype}`,
  265. body: args,
  266. headers: {
  267. Accept: 'application/json',
  268. 'Content-Type': 'application/json',
  269. 'X-Frappe-CSRF-Token': csrf_token
  270. },
  271. failOnStatusCode: !ignore_duplicate
  272. })
  273. .then(res => {
  274. let status_codes = [200];
  275. if (ignore_duplicate) {
  276. status_codes.push(409);
  277. }
  278. expect(res.status).to.be.oneOf(status_codes);
  279. return res.body.data;
  280. });
  281. });
  282. });
  283. Cypress.Commands.add('add_filter', () => {
  284. cy.get('.filter-section .filter-button').click();
  285. cy.wait(300);
  286. cy.get('.filter-popover').should('exist');
  287. cy.get('.filter-popover').find('.add-filter').click();
  288. });
  289. Cypress.Commands.add('clear_filters', () => {
  290. cy.get('.filter-section .filter-button').click();
  291. cy.wait(300);
  292. cy.get('.filter-popover').should('exist');
  293. cy.get('.filter-popover').find('.clear-filters').click();
  294. cy.get('.filter-section .filter-button').click();
  295. cy.window().its('cur_list').then(cur_list => {
  296. cur_list && cur_list.filter_area && cur_list.filter_area.clear();
  297. });
  298. });