auto_wizard_spec.rb 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe AutoWizard do
  4. describe '.enabled?' do
  5. context 'without "auto_wizard.json" file in project root' do
  6. before { FileUtils.rm(Rails.root.join('auto_wizard.json'), force: true) }
  7. it 'returns false' do
  8. expect(described_class.enabled?).to be(false)
  9. end
  10. end
  11. context 'with "auto_wizard.json" file in project root' do
  12. around do |example|
  13. FileUtils.touch(Rails.root.join('auto_wizard.json'))
  14. example.run
  15. FileUtils.rm(Rails.root.join('auto_wizard.json'))
  16. end
  17. it 'returns true' do
  18. expect(described_class.enabled?).to be(true)
  19. end
  20. end
  21. context 'with "auto_wizard.json" file in custom directory' do
  22. before do
  23. allow(ENV).to receive(:[]).with('AUTOWIZARD_RELATIVE_PATH').and_return('tmp/auto_wizard.json')
  24. end
  25. context 'with file present' do
  26. around do |example|
  27. FileUtils.touch(Rails.root.join('tmp/auto_wizard.json'))
  28. example.run
  29. FileUtils.rm(Rails.root.join('tmp/auto_wizard.json'))
  30. end
  31. it 'returns true' do
  32. expect(described_class.enabled?).to be(true)
  33. end
  34. end
  35. context 'with file missing' do
  36. it 'returns true' do
  37. expect(described_class.enabled?).to be(false)
  38. end
  39. end
  40. end
  41. end
  42. describe '.setup' do
  43. around do |example|
  44. Rails.root.join('auto_wizard.json').write(seed_data.to_json)
  45. example.run
  46. FileUtils.rm(Rails.root.join('auto_wizard.json'), force: true)
  47. end
  48. let(:seed_data) { {} }
  49. context 'with a writable file system' do
  50. it 'removes "auto_wizard.json" file when complete' do
  51. expect { described_class.setup }
  52. .to change { Rails.root.join('auto_wizard.json').exist? }.to(false)
  53. end
  54. end
  55. context 'with a read-only file system' do
  56. before do
  57. allow(FileUtils).to receive(:rm).and_raise(Errno::EPERM)
  58. end
  59. it 'cannot remove the auto wizard file, but also does not throw an error' do
  60. expect { described_class.setup }
  61. .not_to change { Rails.root.join('auto_wizard.json').exist? }
  62. end
  63. end
  64. context 'when "auto_wizard.json" contains a set of User attributes and associations (Role names)' do
  65. let(:seed_data) do
  66. {
  67. Users: [
  68. {
  69. login: 'master_unit_test01@example.com',
  70. firstname: 'Test Admin',
  71. lastname: 'Agent',
  72. email: 'master_unit_test01@example.com',
  73. password: 'test',
  74. roles: ['Agent']
  75. }
  76. ]
  77. }
  78. end
  79. it 'creates a user with those attributes and roles' do
  80. expect { described_class.setup }
  81. .to change(User, :count).by(1)
  82. .and change { User.last.roles }.to(Role.where(name: 'Agent'))
  83. .and change { User.last.login }.to('master_unit_test01@example.com')
  84. .and change { User.last.firstname }.to('Test Admin')
  85. .and change { User.last.lastname }.to('Agent')
  86. .and change { User.last.email }.to('master_unit_test01@example.com')
  87. .and(change do
  88. Auth.new(User.last.email, 'test').valid!
  89. rescue Auth::Error::AuthenticationFailed
  90. false
  91. end.from(false))
  92. end
  93. end
  94. context 'when "auto_wizard.json" contains a set of User attributes without associations' do
  95. let(:seed_data) do
  96. {
  97. Users: [
  98. {
  99. login: 'master_unit_test01@example.com',
  100. firstname: 'Test Admin',
  101. lastname: 'Agent',
  102. email: 'master_unit_test01@example.com',
  103. password: 'test'
  104. }
  105. ]
  106. }
  107. end
  108. it 'creates a user with those attributes and Admin + Agent roles' do
  109. expect { described_class.setup }
  110. .to change(User, :count).by(1)
  111. .and change { User.last.roles }.to(Role.where(name: %w[Admin Agent]))
  112. .and change { User.last.login }.to('master_unit_test01@example.com')
  113. .and change { User.last.firstname }.to('Test Admin')
  114. .and change { User.last.lastname }.to('Agent')
  115. .and change { User.last.email }.to('master_unit_test01@example.com')
  116. .and(change do
  117. Auth.new(User.last.email, 'test').valid!
  118. rescue Auth::Error::AuthenticationFailed
  119. false
  120. end.from(false))
  121. end
  122. end
  123. context 'when "auto_wizard.json" contains a set of Group attributes and associations (User emails, Signature name, & EmailAddress id)' do
  124. let(:seed_data) do
  125. {
  126. Groups: [
  127. {
  128. name: 'some group1',
  129. note: 'Lorem ipsum dolor',
  130. users: [group_agent.email],
  131. signature: group_signature.name,
  132. email_address_id: group_email.id,
  133. }
  134. ]
  135. }
  136. end
  137. let(:group_agent) { create(:agent) }
  138. let(:group_signature) { create(:signature) }
  139. let(:group_email) { create(:email_address) }
  140. it 'creates a group with those attributes and associations' do
  141. expect { described_class.setup }
  142. .to change(Group, :count).by(1)
  143. .and change { Group.last.name }.to('some group1')
  144. .and change { Group.last.note }.to('Lorem ipsum dolor')
  145. .and change { Group.last.users }.to([group_agent])
  146. .and change { Group.last.signature }.to(group_signature)
  147. end
  148. end
  149. context 'when "auto_wizard.json" contains a set of EmailAddress attributes' do
  150. let(:seed_data) do
  151. {
  152. EmailAddresses: [
  153. {
  154. channel_id: channel.id,
  155. name: 'John Doe',
  156. email: 'johndoe@example.com',
  157. }
  158. ],
  159. }
  160. end
  161. let(:channel) { create(:email_channel) }
  162. it 'creates an email address with the given attributes' do
  163. expect { described_class.setup }
  164. .to change(EmailAddress, :count)
  165. .and change { EmailAddress.last&.name }.to('John Doe')
  166. .and change { EmailAddress.last&.email }.to('johndoe@example.com')
  167. .and change { EmailAddress.last&.channel }.to(channel)
  168. end
  169. end
  170. context 'when "auto_wizard.json" contains a set of EmailAddress attributes, including an existing ID' do
  171. let(:seed_data) do
  172. {
  173. EmailAddresses: [
  174. {
  175. id: email_address.id,
  176. channel_id: new_channel.id,
  177. name: 'John Doe',
  178. email: 'johndoe@example.com',
  179. }
  180. ],
  181. }
  182. end
  183. let(:email_address) { create(:email_address) }
  184. let(:new_channel) { create(:email_channel) }
  185. it 'updates the specified email address with the given attributes' do
  186. expect { described_class.setup }
  187. .to not_change(EmailAddress, :count)
  188. .and change { email_address.reload.name }.to('John Doe')
  189. .and change { email_address.reload.email }.to('johndoe@example.com')
  190. .and change { email_address.reload.channel }.to(new_channel)
  191. end
  192. end
  193. context 'when "auto_wizard.json" contains a set of Channel attributes' do
  194. let(:seed_data) do
  195. {
  196. Channels: [
  197. {
  198. id: 100,
  199. area: 'Email::Account',
  200. group: 'Users',
  201. options: {
  202. inbound: {
  203. adapter: 'imap',
  204. options: {
  205. host: 'mx1.example.com',
  206. user: 'not_existing',
  207. password: 'some_pass',
  208. ssl: 'ssl'
  209. }
  210. },
  211. outbound: {
  212. adapter: 'sendmail'
  213. }
  214. },
  215. preferences: {
  216. online_service_disable: true,
  217. },
  218. active: true
  219. }
  220. ],
  221. }
  222. end
  223. it 'creates a new channel with the given attributes' do
  224. expect { described_class.setup }
  225. .to change(Channel, :count)
  226. .and change { Channel.last&.group }.to(Group.find_by(name: 'Users'))
  227. .and change { Channel.last&.area }.to('Email::Account')
  228. end
  229. end
  230. context 'when "auto_wizard.json" contains a set of Channel attributes, including an existing ID' do
  231. let(:seed_data) do
  232. {
  233. Channels: [
  234. {
  235. id: channel.id,
  236. area: 'Email::Account',
  237. group: new_group.name,
  238. options: {
  239. inbound: {
  240. adapter: 'imap',
  241. options: {
  242. host: 'mx1.example.com',
  243. user: 'not_existing',
  244. password: 'some_pass',
  245. ssl: 'ssl'
  246. }
  247. },
  248. outbound: {
  249. adapter: 'sendmail'
  250. }
  251. },
  252. preferences: {
  253. online_service_disable: true,
  254. },
  255. active: true
  256. }
  257. ],
  258. }
  259. end
  260. let(:channel) { create(:twitter_channel) }
  261. let(:new_group) { create(:group) }
  262. it 'updates the specified channel with the given attributes' do
  263. expect { described_class.setup }
  264. .to not_change(Channel, :count)
  265. .and change { channel.reload.group }.to(new_group)
  266. .and change { channel.reload.area }.to('Email::Account')
  267. end
  268. end
  269. context 'when "auto_wizard.json" contains a set of existing permission names and active-statuses' do
  270. let(:seed_data) do
  271. {
  272. Permissions: [
  273. {
  274. name: 'admin.session',
  275. active: false,
  276. },
  277. ],
  278. }
  279. end
  280. it 'sets the specified permissions to the given active-statuses' do
  281. expect { described_class.setup }
  282. .to not_change(Permission, :count)
  283. .and change { Permission.find_by(name: 'admin.session').active }.to(false)
  284. end
  285. end
  286. context 'when "auto_wizard.json" contains a set of new permission names and active-statuses' do
  287. let(:seed_data) do
  288. {
  289. Permissions: [
  290. {
  291. name: 'admin.session.new',
  292. active: false,
  293. },
  294. ],
  295. }
  296. end
  297. it 'creates a new permission with the given active-status' do
  298. expect { described_class.setup }
  299. .to change(Permission, :count).by(1)
  300. .and change { Permission.last.name }.to('admin.session.new')
  301. .and change { Permission.last.active }.to(false)
  302. end
  303. end
  304. context 'when "auto_wizard.json" contains sets of existing Setting names and values' do
  305. let(:seed_data) do
  306. {
  307. Settings: [
  308. {
  309. name: 'developer_mode',
  310. value: true
  311. },
  312. {
  313. name: 'product_name',
  314. value: 'Zammad UnitTest01 System'
  315. }
  316. ]
  317. }
  318. end
  319. it 'sets the specified settings to the given values' do
  320. expect { described_class.setup }
  321. .to change { Setting.get('developer_mode') }.to(true)
  322. .and change { Setting.get('product_name') }.to('Zammad UnitTest01 System')
  323. end
  324. end
  325. context 'when "auto_wizard.json" contains a TextModule locale' do
  326. let(:seed_data) do
  327. {
  328. TextModuleLocale: {
  329. Locale: 'de-de'
  330. }
  331. }
  332. end
  333. it 'creates a full set of text modules for the specified locale' do
  334. expect { described_class.setup }
  335. .to change(TextModule, :count)
  336. end
  337. end
  338. context 'when "auto_wizard.json" contains a Calendar IP' do
  339. let(:seed_data) do
  340. {
  341. CalendarSetup: {
  342. Ip: '195.65.29.254',
  343. },
  344. }
  345. end
  346. it 'updates the existing calendar with the specified IP' do
  347. expect { described_class.setup }
  348. .to not_change(Calendar, :count)
  349. .and change { Calendar.last.name }.to('Switzerland')
  350. .and change { Calendar.last.timezone }.to('Europe/Zurich')
  351. end
  352. end
  353. end
  354. end