user_csv_import_test.rb 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. require 'test_helper'
  3. class UserCsvImportTest < ActiveSupport::TestCase
  4. test 'import example verify' do
  5. csv_string = User.csv_example
  6. rows = CSV.parse(csv_string)
  7. header = rows.shift
  8. assert_equal('id', header[0])
  9. assert_equal('login', header[1])
  10. assert_equal('firstname', header[2])
  11. assert_equal('lastname', header[3])
  12. assert_equal('email', header[4])
  13. assert(header.include?('organization'))
  14. end
  15. test 'empty payload' do
  16. csv_string = ''
  17. result = User.csv_import(
  18. string: csv_string,
  19. parse_params: {
  20. col_sep: ';',
  21. },
  22. try: true,
  23. )
  24. assert_equal(true, result[:try])
  25. assert_nil(result[:records])
  26. assert_equal('failed', result[:result])
  27. assert_equal('Unable to parse empty file/string for User.', result[:errors][0])
  28. csv_string = "login;firstname;lastname;email;active;\n"
  29. result = User.csv_import(
  30. string: csv_string,
  31. parse_params: {
  32. col_sep: ';',
  33. },
  34. try: true,
  35. )
  36. assert_equal(true, result[:try])
  37. assert(result[:records].blank?)
  38. assert_equal('failed', result[:result])
  39. assert_equal('No records found in file/string for User.', result[:errors][0])
  40. end
  41. test 'verify required lookup headers' do
  42. csv_string = "firstname;lastname;active;\nfirstname-simple-import1;lastname-simple-import1;;true\nfirstname-simple-import2;lastname-simple-import2;false\n"
  43. result = User.csv_import(
  44. string: csv_string,
  45. parse_params: {
  46. col_sep: ';',
  47. },
  48. try: true,
  49. )
  50. assert_equal(true, result[:try])
  51. assert_equal('failed', result[:result])
  52. assert_equal('No lookup column like id,login,email for User found.', result[:errors][0])
  53. end
  54. test 'simple import' do
  55. count = User.count
  56. csv_string = "login;firstname;lastname;email;active;\nuser-simple-IMPORT1;firstname-simple-import1;lastname-simple-import1;user-simple-IMPORT1@example.com ;true\nuser-simple-import2;firstname-simple-import2;lastname-simple-import2;user-simple-import2@example.com;false\n"
  57. result = User.csv_import(
  58. string: csv_string,
  59. parse_params: {
  60. col_sep: ';',
  61. },
  62. try: true,
  63. )
  64. assert_equal(true, result[:try])
  65. assert_equal(2, result[:records].count)
  66. assert_equal('success', result[:result])
  67. assert_equal(2, result[:stats][:created])
  68. assert_equal(0, result[:stats][:updated])
  69. assert_equal(count, User.count)
  70. assert_nil(User.find_by(login: 'user-simple-import1'))
  71. assert_nil(User.find_by(login: 'user-simple-import2'))
  72. result = User.csv_import(
  73. string: csv_string,
  74. parse_params: {
  75. col_sep: ';',
  76. },
  77. try: false,
  78. )
  79. assert_equal(false, result[:try])
  80. assert_equal(2, result[:records].count)
  81. assert_equal('success', result[:result])
  82. assert_equal(2, result[:stats][:created])
  83. assert_equal(0, result[:stats][:updated])
  84. assert_equal(count + 2, User.count)
  85. user1 = User.find_by(login: 'user-simple-import1')
  86. assert(user1)
  87. assert_equal(user1.login, 'user-simple-import1')
  88. assert_equal(user1.firstname, 'firstname-simple-import1')
  89. assert_equal(user1.lastname, 'lastname-simple-import1')
  90. assert_equal(user1.email, 'user-simple-import1@example.com')
  91. assert_equal(user1.active, true)
  92. user2 = User.find_by(login: 'user-simple-import2')
  93. assert(user2)
  94. assert_equal(user2.login, 'user-simple-import2')
  95. assert_equal(user2.firstname, 'firstname-simple-import2')
  96. assert_equal(user2.lastname, 'lastname-simple-import2')
  97. assert_equal(user2.email, 'user-simple-import2@example.com')
  98. assert_equal(user2.active, false)
  99. result = User.csv_import(
  100. string: csv_string,
  101. parse_params: {
  102. col_sep: ';',
  103. },
  104. try: false,
  105. )
  106. assert_equal(false, result[:try])
  107. assert_equal(2, result[:records].count)
  108. assert_equal('success', result[:result])
  109. assert_equal(0, result[:stats][:created])
  110. assert_equal(2, result[:stats][:updated])
  111. assert_equal(count + 2, User.count)
  112. user1_1 = user1
  113. user1 = User.find_by(login: 'user-simple-import1')
  114. assert(user1)
  115. assert_equal(user1.login, 'user-simple-import1')
  116. assert_equal(user1.firstname, 'firstname-simple-import1')
  117. assert_equal(user1.lastname, 'lastname-simple-import1')
  118. assert_equal(user1.email, 'user-simple-import1@example.com')
  119. assert_equal(user1.active, true)
  120. assert_equal(user1.updated_at, user1_1.updated_at)
  121. user2_1 = user2
  122. user2 = User.find_by(login: 'user-simple-import2')
  123. assert(user2)
  124. assert_equal(user2.login, 'user-simple-import2')
  125. assert_equal(user2.firstname, 'firstname-simple-import2')
  126. assert_equal(user2.lastname, 'lastname-simple-import2')
  127. assert_equal(user2.email, 'user-simple-import2@example.com')
  128. assert_equal(user2.active, false)
  129. assert_equal(user2.updated_at, user2_1.updated_at)
  130. travel 2.seconds
  131. csv_string = "login;firstname;lastname;email;active;\n ;firstname-simple-import1;lastname-simple-import1;user-simple-IMPORT1@example.com ;true\n user-simple-import2\t;firstname-simple-import2;lastname-simple-import2;;false\n"
  132. result = User.csv_import(
  133. string: csv_string,
  134. parse_params: {
  135. col_sep: ';',
  136. },
  137. try: false,
  138. )
  139. assert_equal(false, result[:try])
  140. assert_equal(2, result[:records].count)
  141. assert_equal(0, result[:stats][:created])
  142. assert_equal(2, result[:stats][:updated])
  143. assert_equal('success', result[:result])
  144. assert_equal(count + 2, User.count)
  145. user1_1 = user1
  146. user1 = User.find_by(email: 'user-simple-import1@example.com')
  147. assert(user1)
  148. assert_equal(user1.login, 'user-simple-import1@example.com')
  149. assert_equal(user1.firstname, 'firstname-simple-import1')
  150. assert_equal(user1.lastname, 'lastname-simple-import1')
  151. assert_equal(user1.email, 'user-simple-import1@example.com')
  152. assert_equal(user1.active, true)
  153. assert_not_equal(user1.updated_at, user1_1.updated_at)
  154. user2_1 = user2
  155. user2 = User.find_by(login: 'user-simple-import2')
  156. assert(user2)
  157. assert_equal(user2.login, 'user-simple-import2')
  158. assert_equal(user2.firstname, 'firstname-simple-import2')
  159. assert_equal(user2.lastname, 'lastname-simple-import2')
  160. assert_equal(user2.email, 'user-simple-import2@example.com')
  161. assert_equal(user2.active, false)
  162. assert_equal(user2.updated_at, user2_1.updated_at)
  163. user1.destroy!
  164. user2.destroy!
  165. end
  166. test 'simple import with invalid id' do
  167. csv_string = "id;login;firstname;lastname;email;active;\n999999999;user-simple-invalid_id-import1;firstname-simple-import1;lastname-simple-import1;user-simple-invalid_id-import1@example.com;true\n;user-simple-invalid_id-import2;firstname-simple-import2;lastname-simple-import2;user-simple-invalid_id-import2@example.com;false\n"
  168. result = User.csv_import(
  169. string: csv_string,
  170. parse_params: {
  171. col_sep: ';',
  172. },
  173. try: true,
  174. )
  175. assert_equal(true, result[:try])
  176. assert_equal(1, result[:errors].count)
  177. assert_equal('failed', result[:result])
  178. assert_equal("Line 1: unknown User with id '999999999'.", result[:errors][0])
  179. assert_nil(User.find_by(login: 'user-simple-invalid_id-import1'))
  180. assert_nil(User.find_by(login: 'user-simple-invalid_id-import2'))
  181. result = User.csv_import(
  182. string: csv_string,
  183. parse_params: {
  184. col_sep: ';',
  185. },
  186. try: false,
  187. )
  188. assert_equal(false, result[:try])
  189. assert_equal(1, result[:records].count)
  190. assert_equal('failed', result[:result])
  191. assert_nil(User.find_by(login: 'user-simple-invalid_id-import1'))
  192. # any single failure will cause the entire import to be aborted
  193. assert_nil(User.find_by(login: 'user-simple-invalid_id-import2'))
  194. end
  195. test 'simple import with read only id' do
  196. csv_string = "id;login;firstname;lastname;email;active;\n1;user-simple-readonly_id-import1;firstname-simple-import1;lastname-simple-import1;user-simple-readonly_id-import1@example.com;true\n;user-simple-readonly_id-import2;firstname-simple-import2;lastname-simple-import2;user-simple-readonly_id-import2@example.com;false\n"
  197. result = User.csv_import(
  198. string: csv_string,
  199. parse_params: {
  200. col_sep: ';',
  201. },
  202. try: true,
  203. )
  204. assert_equal(true, result[:try])
  205. assert_equal(1, result[:errors].count)
  206. assert_equal('failed', result[:result])
  207. assert_equal("Line 1: unable to update User with id '1'.", result[:errors][0])
  208. assert_nil(User.find_by(login: 'user-simple-readonly_id-import1'))
  209. assert_nil(User.find_by(login: 'user-simple-readonly_id-import2'))
  210. result = User.csv_import(
  211. string: csv_string,
  212. parse_params: {
  213. col_sep: ';',
  214. },
  215. try: false,
  216. )
  217. assert_equal(false, result[:try])
  218. assert_equal(1, result[:records].count)
  219. assert_equal('failed', result[:result])
  220. assert_nil(User.find_by(login: 'user-simple-readonly_id-import1'))
  221. # any single failure will cause the entire import to be aborted
  222. assert_nil(User.find_by(login: 'user-simple-readonly_id-import2'))
  223. end
  224. test 'simple import with roles' do
  225. UserInfo.current_user_id = 1
  226. admin = User.create_or_update(
  227. login: 'admin1@example.com',
  228. firstname: 'Admin',
  229. lastname: '1',
  230. email: 'admin1@example.com',
  231. password: 'agentpw',
  232. active: true,
  233. roles: Role.where(name: 'Admin'),
  234. )
  235. csv_string = "login;firstname;lastname;email;roles;\nuser-role-import1;firstname-role-import1;lastname-role-import1;user-role-import1@example.com;Customer;\nuser-role-import2;firstname-role-import2;lastname-role-import2;user-role-import2@example.com;Agent\n;;;;Admin"
  236. result = User.csv_import(
  237. string: csv_string,
  238. parse_params: {
  239. col_sep: ';',
  240. },
  241. try: true,
  242. )
  243. assert_equal(true, result[:try])
  244. assert_equal(2, result[:records].count)
  245. assert_equal('success', result[:result])
  246. assert_nil(User.find_by(login: 'user-role-import1'))
  247. assert_nil(User.find_by(login: 'user-role-import2'))
  248. result = User.csv_import(
  249. string: csv_string,
  250. parse_params: {
  251. col_sep: ';',
  252. },
  253. try: false,
  254. )
  255. assert_equal(false, result[:try])
  256. assert_equal(2, result[:records].count)
  257. assert_equal('success', result[:result])
  258. user1 = User.find_by(login: 'user-role-import1')
  259. assert(user1)
  260. assert_equal(user1.login, 'user-role-import1')
  261. assert_equal(user1.firstname, 'firstname-role-import1')
  262. assert_equal(user1.lastname, 'lastname-role-import1')
  263. assert_equal(user1.email, 'user-role-import1@example.com')
  264. assert_equal(user1.roles.count, 1)
  265. user2 = User.find_by(login: 'user-role-import2')
  266. assert(user2)
  267. assert_equal(user2.login, 'user-role-import2')
  268. assert_equal(user2.firstname, 'firstname-role-import2')
  269. assert_equal(user2.lastname, 'lastname-role-import2')
  270. assert_equal(user2.email, 'user-role-import2@example.com')
  271. assert_equal(user2.roles.count, 2)
  272. user1.destroy!
  273. user2.destroy!
  274. admin.destroy!
  275. end
  276. test 'simple import + fixed params' do
  277. csv_string = "login;firstname;lastname;email\nuser-simple-import-fixed1;firstname-simple-import-fixed1;lastname-simple-import-fixed1;user-simple-import-fixed1@example.com\nuser-simple-import-fixed2;firstname-simple-import-fixed2;lastname-simple-import-fixed2;user-simple-import-fixed2@example.com\n"
  278. result = User.csv_import(
  279. string: csv_string,
  280. parse_params: {
  281. col_sep: ';',
  282. },
  283. fixed_params: {
  284. note: 'some note',
  285. },
  286. try: true,
  287. )
  288. assert_equal(true, result[:try])
  289. assert_equal(2, result[:records].count)
  290. assert_equal('success', result[:result])
  291. assert_nil(User.find_by(login: 'user-simple-import-fixed1'))
  292. assert_nil(User.find_by(login: 'user-simple-import-fixed2'))
  293. result = User.csv_import(
  294. string: csv_string,
  295. parse_params: {
  296. col_sep: ';',
  297. },
  298. fixed_params: {
  299. note: 'some note',
  300. },
  301. try: false,
  302. )
  303. assert_equal(false, result[:try])
  304. assert_equal(2, result[:records].count)
  305. assert_equal('success', result[:result])
  306. user1 = User.find_by(login: 'user-simple-import-fixed1')
  307. user2 = User.find_by(login: 'user-simple-import-fixed2')
  308. assert(user1)
  309. assert_equal('some note', user1.note)
  310. assert_equal('user-simple-import-fixed1', user1.login)
  311. assert_equal('firstname-simple-import-fixed1', user1.firstname)
  312. assert_equal('lastname-simple-import-fixed1', user1.lastname)
  313. assert_equal('user-simple-import-fixed1@example.com', user1.email)
  314. assert(user2)
  315. assert_equal('some note', user2.note)
  316. assert_equal('user-simple-import-fixed2', user2.login)
  317. assert_equal('firstname-simple-import-fixed2', user2.firstname)
  318. assert_equal('lastname-simple-import-fixed2', user2.lastname)
  319. assert_equal('user-simple-import-fixed2@example.com', user2.email)
  320. user1.destroy!
  321. user2.destroy!
  322. end
  323. test 'duplicate import' do
  324. csv_string = "login;firstname;lastname;email\nuser-duplicate-import1;firstname-duplicate-import1;firstname-duplicate-import1;user-duplicate-import1@example.com\nuser-duplicate-import2;firstname-duplicate-import2;firstname-duplicate-import2;user-duplicate-import2@example.com\nuser-duplicate-import2;firstname-duplicate-import3;firstname-duplicate-import3;user-duplicate-import3@example.com"
  325. result = User.csv_import(
  326. string: csv_string,
  327. parse_params: {
  328. col_sep: ';',
  329. },
  330. try: true,
  331. )
  332. assert_equal(true, result[:try])
  333. assert_equal(2, result[:records].count)
  334. assert_equal('failed', result[:result])
  335. assert_nil(User.find_by(login: 'user-duplicate-import1'))
  336. assert_nil(User.find_by(login: 'user-duplicate-import2'))
  337. assert_nil(User.find_by(login: 'user-duplicate-import3'))
  338. result = User.csv_import(
  339. string: csv_string,
  340. parse_params: {
  341. col_sep: ';',
  342. },
  343. try: false,
  344. )
  345. assert_equal(false, result[:try])
  346. assert_equal(2, result[:records].count)
  347. assert_equal('failed', result[:result])
  348. assert_nil(User.find_by(login: 'user-duplicate-import1'))
  349. assert_nil(User.find_by(login: 'user-duplicate-import2'))
  350. assert_nil(User.find_by(login: 'user-duplicate-import3'))
  351. end
  352. test 'invalid attributes' do
  353. csv_string = "login;firstname2;lastname;email\nuser-invalid-import1;firstname-invalid-import1;firstname-invalid-import1;user-invalid-import1@example.com\nuser-invalid-import2;firstname-invalid-import2;firstname-invalid-import2;user-invalid-import2@example.com\n"
  354. result = User.csv_import(
  355. string: csv_string,
  356. parse_params: {
  357. col_sep: ';',
  358. },
  359. try: true,
  360. )
  361. assert_equal(true, result[:try])
  362. assert_equal(2, result[:errors].count)
  363. assert_equal('failed', result[:result])
  364. assert_equal("Line 1: Unable to create record - unknown attribute 'firstname2' for User.", result[:errors][0])
  365. assert_equal("Line 2: Unable to create record - unknown attribute 'firstname2' for User.", result[:errors][1])
  366. assert_nil(User.find_by(login: 'user-invalid-import1'))
  367. assert_nil(User.find_by(login: 'user-invalid-import2'))
  368. result = User.csv_import(
  369. string: csv_string,
  370. parse_params: {
  371. col_sep: ';',
  372. },
  373. try: false,
  374. )
  375. assert_equal(false, result[:try])
  376. assert_equal(2, result[:errors].count)
  377. assert_equal('failed', result[:result])
  378. assert_equal("Line 1: Unable to create record - unknown attribute 'firstname2' for User.", result[:errors][0])
  379. assert_equal("Line 2: Unable to create record - unknown attribute 'firstname2' for User.", result[:errors][1])
  380. assert_nil(User.find_by(login: 'user-invalid-import1'))
  381. assert_nil(User.find_by(login: 'user-invalid-import2'))
  382. end
  383. test 'reference import' do
  384. csv_string = "login;firstname;lastname;email;organization\nuser-reference-import1;firstname-reference-import1;firstname-reference-import1;user-reference-import1@example.com;organization-reference-import1\nuser-reference-import2;firstname-reference-import2;firstname-reference-import2;user-reference-import2@example.com;organization-reference-import2\nuser-reference-import3;firstname-reference-import3;firstname-reference-import3;user-reference-import3@example.com;Zammad Foundation\n"
  385. result = User.csv_import(
  386. string: csv_string,
  387. parse_params: {
  388. col_sep: ';',
  389. },
  390. try: true,
  391. )
  392. assert_equal(true, result[:try])
  393. assert_equal(2, result[:errors].count)
  394. assert_equal('failed', result[:result])
  395. assert_nil(User.find_by(login: 'user-reference-import1'))
  396. assert_nil(User.find_by(login: 'user-reference-import2'))
  397. assert_nil(User.find_by(login: 'user-reference-import3'))
  398. assert_equal("Line 1: No lookup value found for 'organization': \"organization-reference-import1\"", result[:errors][0])
  399. assert_equal("Line 2: No lookup value found for 'organization': \"organization-reference-import2\"", result[:errors][1])
  400. result = User.csv_import(
  401. string: csv_string,
  402. parse_params: {
  403. col_sep: ';',
  404. },
  405. try: false,
  406. )
  407. assert_equal(false, result[:try])
  408. assert_equal(2, result[:errors].count)
  409. assert_equal('failed', result[:result])
  410. assert_nil(User.find_by(login: 'user-reference-import1'))
  411. assert_nil(User.find_by(login: 'user-reference-import2'))
  412. assert_nil(User.find_by(login: 'user-reference-import3'))
  413. assert_equal("Line 1: No lookup value found for 'organization': \"organization-reference-import1\"", result[:errors][0])
  414. assert_equal("Line 2: No lookup value found for 'organization': \"organization-reference-import2\"", result[:errors][1])
  415. UserInfo.current_user_id = 1
  416. orgaization1 = Organization.create_if_not_exists(name: 'organization-reference-import1')
  417. orgaization2 = Organization.create_if_not_exists(name: 'organization-reference-import2')
  418. result = User.csv_import(
  419. string: csv_string,
  420. parse_params: {
  421. col_sep: ';',
  422. },
  423. try: true,
  424. )
  425. assert_equal(true, result[:try])
  426. assert_equal(0, result[:errors].count)
  427. assert_equal('success', result[:result])
  428. assert_nil(User.find_by(login: 'user-reference-import1'))
  429. assert_nil(User.find_by(login: 'user-reference-import2'))
  430. # any single failure will cause the entire import to be aborted
  431. assert_nil(User.find_by(login: 'user-reference-import3'))
  432. result = User.csv_import(
  433. string: csv_string,
  434. parse_params: {
  435. col_sep: ';',
  436. },
  437. try: false,
  438. )
  439. assert_equal(false, result[:try])
  440. assert_equal(0, result[:errors].count)
  441. assert_equal('success', result[:result])
  442. assert(User.find_by(login: 'user-reference-import1'))
  443. assert(User.find_by(login: 'user-reference-import2'))
  444. assert(User.find_by(login: 'user-reference-import3'))
  445. User.find_by(login: 'user-reference-import1').destroy!
  446. User.find_by(login: 'user-reference-import2').destroy!
  447. User.find_by(login: 'user-reference-import3').destroy!
  448. orgaization1.destroy!
  449. orgaization2.destroy!
  450. end
  451. test 'simple import with delete' do
  452. csv_string = "login;firstname;lastname;email\nuser-simple-import-fixed1;firstname-simple-import-fixed1;lastname-simple-import-fixed1;user-simple-import-fixed1@example.com\nuser-simple-import-fixed2;firstname-simple-import-fixed2;lastname-simple-import-fixed2;user-simple-import-fixed2@example.com\n"
  453. result = User.csv_import(
  454. string: csv_string,
  455. parse_params: {
  456. col_sep: ';',
  457. },
  458. try: true,
  459. delete: true,
  460. )
  461. assert_equal(true, result[:try])
  462. assert_equal('failed', result[:result])
  463. assert_equal('Delete is not possible for User.', result[:errors][0])
  464. end
  465. end