4
0

integration_test.go 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
  1. // Copyright 2017 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. // +build integration
  5. package main
  6. import (
  7. "bytes"
  8. "io/ioutil"
  9. "math/rand"
  10. "strconv"
  11. "strings"
  12. "testing"
  13. "time"
  14. "github.com/miniflux/miniflux-go"
  15. )
  16. const (
  17. testBaseURL = "http://127.0.0.1:8080/"
  18. testAdminUsername = "admin"
  19. testAdminPassword = "test123"
  20. testStandardPassword = "secret"
  21. testFeedURL = "https://github.com/miniflux/miniflux/commits/master.atom"
  22. testFeedTitle = "Recent Commits to miniflux:master"
  23. testWebsiteURL = "https://github.com/miniflux/miniflux/commits/master"
  24. )
  25. func TestWithBadEndpoint(t *testing.T) {
  26. client := miniflux.NewClient("bad url", testAdminUsername, testAdminPassword)
  27. _, err := client.Users()
  28. if err == nil {
  29. t.Fatal(`Using a bad url should raise an error`)
  30. }
  31. }
  32. func TestWithWrongCredentials(t *testing.T) {
  33. client := miniflux.NewClient(testBaseURL, "invalid", "invalid")
  34. _, err := client.Users()
  35. if err == nil {
  36. t.Fatal(`Using bad credentials should raise an error`)
  37. }
  38. }
  39. func TestGetUsers(t *testing.T) {
  40. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  41. users, err := client.Users()
  42. if err != nil {
  43. t.Fatal(err)
  44. }
  45. if len(users) == 0 {
  46. t.Fatal("The list of users is empty")
  47. }
  48. if users[0].ID == 0 {
  49. t.Fatalf(`Invalid userID, got "%v"`, users[0].ID)
  50. }
  51. if users[0].Username != testAdminUsername {
  52. t.Fatalf(`Invalid username, got "%v" instead of "%v"`, users[0].Username, testAdminUsername)
  53. }
  54. if users[0].Password != "" {
  55. t.Fatalf(`Invalid password, got "%v"`, users[0].Password)
  56. }
  57. if users[0].Language != "en_US" {
  58. t.Fatalf(`Invalid language, got "%v"`, users[0].Language)
  59. }
  60. if users[0].Theme != "default" {
  61. t.Fatalf(`Invalid theme, got "%v"`, users[0].Theme)
  62. }
  63. if users[0].Timezone != "UTC" {
  64. t.Fatalf(`Invalid timezone, got "%v"`, users[0].Timezone)
  65. }
  66. if !users[0].IsAdmin {
  67. t.Fatalf(`Invalid role, got "%v"`, users[0].IsAdmin)
  68. }
  69. }
  70. func TestCreateStandardUser(t *testing.T) {
  71. username := getRandomUsername()
  72. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  73. user, err := client.CreateUser(username, testStandardPassword, false)
  74. if err != nil {
  75. t.Fatal(err)
  76. }
  77. if user.ID == 0 {
  78. t.Fatalf(`Invalid userID, got "%v"`, user.ID)
  79. }
  80. if user.Username != username {
  81. t.Fatalf(`Invalid username, got "%v" instead of "%v"`, user.Username, username)
  82. }
  83. if user.Password != "" {
  84. t.Fatalf(`Invalid password, got "%v"`, user.Password)
  85. }
  86. if user.Language != "en_US" {
  87. t.Fatalf(`Invalid language, got "%v"`, user.Language)
  88. }
  89. if user.Theme != "default" {
  90. t.Fatalf(`Invalid theme, got "%v"`, user.Theme)
  91. }
  92. if user.Timezone != "UTC" {
  93. t.Fatalf(`Invalid timezone, got "%v"`, user.Timezone)
  94. }
  95. if user.IsAdmin {
  96. t.Fatalf(`Invalid role, got "%v"`, user.IsAdmin)
  97. }
  98. if user.LastLoginAt != nil {
  99. t.Fatalf(`Invalid last login date, got "%v"`, user.LastLoginAt)
  100. }
  101. }
  102. func TestRemoveUser(t *testing.T) {
  103. username := getRandomUsername()
  104. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  105. user, err := client.CreateUser(username, testStandardPassword, false)
  106. if err != nil {
  107. t.Fatal(err)
  108. }
  109. if err := client.DeleteUser(user.ID); err != nil {
  110. t.Fatalf(`Unable to remove user: "%v"`, err)
  111. }
  112. }
  113. func TestGetUserByID(t *testing.T) {
  114. username := getRandomUsername()
  115. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  116. user, err := client.CreateUser(username, testStandardPassword, false)
  117. if err != nil {
  118. t.Fatal(err)
  119. }
  120. _, err = client.UserByID(99999)
  121. if err == nil {
  122. t.Fatal(`Should returns a 404`)
  123. }
  124. user, err = client.UserByID(user.ID)
  125. if err != nil {
  126. t.Fatal(err)
  127. }
  128. if user.ID == 0 {
  129. t.Fatalf(`Invalid userID, got "%v"`, user.ID)
  130. }
  131. if user.Username != username {
  132. t.Fatalf(`Invalid username, got "%v" instead of "%v"`, user.Username, username)
  133. }
  134. if user.Password != "" {
  135. t.Fatalf(`Invalid password, got "%v"`, user.Password)
  136. }
  137. if user.Language != "en_US" {
  138. t.Fatalf(`Invalid language, got "%v"`, user.Language)
  139. }
  140. if user.Theme != "default" {
  141. t.Fatalf(`Invalid theme, got "%v"`, user.Theme)
  142. }
  143. if user.Timezone != "UTC" {
  144. t.Fatalf(`Invalid timezone, got "%v"`, user.Timezone)
  145. }
  146. if user.IsAdmin {
  147. t.Fatalf(`Invalid role, got "%v"`, user.IsAdmin)
  148. }
  149. if user.LastLoginAt != nil {
  150. t.Fatalf(`Invalid last login date, got "%v"`, user.LastLoginAt)
  151. }
  152. }
  153. func TestGetUserByUsername(t *testing.T) {
  154. username := getRandomUsername()
  155. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  156. user, err := client.CreateUser(username, testStandardPassword, false)
  157. if err != nil {
  158. t.Fatal(err)
  159. }
  160. _, err = client.UserByUsername("missinguser")
  161. if err == nil {
  162. t.Fatal(`Should returns a 404`)
  163. }
  164. user, err = client.UserByUsername(username)
  165. if err != nil {
  166. t.Fatal(err)
  167. }
  168. if user.ID == 0 {
  169. t.Fatalf(`Invalid userID, got "%v"`, user.ID)
  170. }
  171. if user.Username != username {
  172. t.Fatalf(`Invalid username, got "%v" instead of "%v"`, user.Username, username)
  173. }
  174. if user.Password != "" {
  175. t.Fatalf(`Invalid password, got "%v"`, user.Password)
  176. }
  177. if user.Language != "en_US" {
  178. t.Fatalf(`Invalid language, got "%v"`, user.Language)
  179. }
  180. if user.Theme != "default" {
  181. t.Fatalf(`Invalid theme, got "%v"`, user.Theme)
  182. }
  183. if user.Timezone != "UTC" {
  184. t.Fatalf(`Invalid timezone, got "%v"`, user.Timezone)
  185. }
  186. if user.IsAdmin {
  187. t.Fatalf(`Invalid role, got "%v"`, user.IsAdmin)
  188. }
  189. if user.LastLoginAt != nil {
  190. t.Fatalf(`Invalid last login date, got "%v"`, user.LastLoginAt)
  191. }
  192. }
  193. func TestUpdateUser(t *testing.T) {
  194. username := getRandomUsername()
  195. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  196. user, err := client.CreateUser(username, testStandardPassword, false)
  197. if err != nil {
  198. t.Fatal(err)
  199. }
  200. theme := "black"
  201. user.Theme = theme
  202. user, err = client.UpdateUser(user)
  203. if err != nil {
  204. t.Fatal(err)
  205. }
  206. if user.Theme != theme {
  207. t.Fatalf(`Unable to update user: got "%v" instead of "%v"`, user.Theme, theme)
  208. }
  209. }
  210. func TestUpdateUserWithInvalidValue(t *testing.T) {
  211. username := getRandomUsername()
  212. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  213. user, err := client.CreateUser(username, testStandardPassword, false)
  214. if err != nil {
  215. t.Fatal(err)
  216. }
  217. theme := "something that doesn't exists"
  218. user.Theme = theme
  219. _, err = client.UpdateUser(user)
  220. if err == nil {
  221. t.Fatal(`Updating a user with an invalid value should raise an error`)
  222. }
  223. }
  224. func TestCannotCreateDuplicateUser(t *testing.T) {
  225. username := getRandomUsername()
  226. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  227. _, err := client.CreateUser(username, testStandardPassword, false)
  228. if err != nil {
  229. t.Fatal(err)
  230. }
  231. _, err = client.CreateUser(username, testStandardPassword, false)
  232. if err == nil {
  233. t.Fatal(`Duplicate users should not be allowed`)
  234. }
  235. }
  236. func TestCannotListUsersAsNonAdmin(t *testing.T) {
  237. username := getRandomUsername()
  238. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  239. _, err := client.CreateUser(username, testStandardPassword, false)
  240. if err != nil {
  241. t.Fatal(err)
  242. }
  243. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  244. _, err = client.Users()
  245. if err == nil {
  246. t.Fatal(`Standard users should not be able to list any users`)
  247. }
  248. }
  249. func TestCannotGetUserAsNonAdmin(t *testing.T) {
  250. username := getRandomUsername()
  251. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  252. user, err := client.CreateUser(username, testStandardPassword, false)
  253. if err != nil {
  254. t.Fatal(err)
  255. }
  256. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  257. _, err = client.UserByID(user.ID)
  258. if err == nil {
  259. t.Fatal(`Standard users should not be able to get any users`)
  260. }
  261. }
  262. func TestCannotUpdateUserAsNonAdmin(t *testing.T) {
  263. username := getRandomUsername()
  264. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  265. user, err := client.CreateUser(username, testStandardPassword, false)
  266. if err != nil {
  267. t.Fatal(err)
  268. }
  269. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  270. _, err = client.UpdateUser(user)
  271. if err == nil {
  272. t.Fatal(`Standard users should not be able to update any users`)
  273. }
  274. }
  275. func TestCannotCreateUserAsNonAdmin(t *testing.T) {
  276. username := getRandomUsername()
  277. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  278. _, err := client.CreateUser(username, testStandardPassword, false)
  279. if err != nil {
  280. t.Fatal(err)
  281. }
  282. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  283. _, err = client.CreateUser(username, testStandardPassword, false)
  284. if err == nil {
  285. t.Fatal(`Standard users should not be able to create users`)
  286. }
  287. }
  288. func TestCannotDeleteUserAsNonAdmin(t *testing.T) {
  289. username := getRandomUsername()
  290. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  291. user, err := client.CreateUser(username, testStandardPassword, false)
  292. if err != nil {
  293. t.Fatal(err)
  294. }
  295. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  296. if err := client.DeleteUser(user.ID); err == nil {
  297. t.Fatal(`Standard users should not be able to remove any users`)
  298. }
  299. }
  300. func TestCreateCategory(t *testing.T) {
  301. username := getRandomUsername()
  302. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  303. user, err := client.CreateUser(username, testStandardPassword, false)
  304. if err != nil {
  305. t.Fatal(err)
  306. }
  307. categoryName := "My category"
  308. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  309. category, err := client.CreateCategory(categoryName)
  310. if err != nil {
  311. t.Fatal(err)
  312. }
  313. if category.ID == 0 {
  314. t.Fatalf(`Invalid categoryID, got "%v"`, category.ID)
  315. }
  316. if category.UserID != user.ID {
  317. t.Fatalf(`Invalid userID, got "%v" instead of "%v"`, category.UserID, user.ID)
  318. }
  319. if category.Title != categoryName {
  320. t.Fatalf(`Invalid title, got "%v" instead of "%v"`, category.Title, categoryName)
  321. }
  322. }
  323. func TestCreateCategoryWithEmptyTitle(t *testing.T) {
  324. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  325. _, err := client.CreateCategory("")
  326. if err == nil {
  327. t.Fatal(`The category title should be mandatory`)
  328. }
  329. }
  330. func TestCannotCreateDuplicatedCategory(t *testing.T) {
  331. username := getRandomUsername()
  332. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  333. _, err := client.CreateUser(username, testStandardPassword, false)
  334. if err != nil {
  335. t.Fatal(err)
  336. }
  337. categoryName := "My category"
  338. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  339. _, err = client.CreateCategory(categoryName)
  340. if err != nil {
  341. t.Fatal(err)
  342. }
  343. _, err = client.CreateCategory(categoryName)
  344. if err == nil {
  345. t.Fatal(`Duplicated categories should not be allowed`)
  346. }
  347. }
  348. func TestUpdateCategory(t *testing.T) {
  349. username := getRandomUsername()
  350. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  351. user, err := client.CreateUser(username, testStandardPassword, false)
  352. if err != nil {
  353. t.Fatal(err)
  354. }
  355. categoryName := "My category"
  356. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  357. category, err := client.CreateCategory(categoryName)
  358. if err != nil {
  359. t.Fatal(err)
  360. }
  361. categoryName = "Updated category"
  362. category, err = client.UpdateCategory(category.ID, categoryName)
  363. if err != nil {
  364. t.Fatal(err)
  365. }
  366. if category.ID == 0 {
  367. t.Fatalf(`Invalid categoryID, got "%v"`, category.ID)
  368. }
  369. if category.UserID != user.ID {
  370. t.Fatalf(`Invalid userID, got "%v" instead of "%v"`, category.UserID, user.ID)
  371. }
  372. if category.Title != categoryName {
  373. t.Fatalf(`Invalid title, got "%v" instead of "%v"`, category.Title, categoryName)
  374. }
  375. }
  376. func TestListCategories(t *testing.T) {
  377. username := getRandomUsername()
  378. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  379. user, err := client.CreateUser(username, testStandardPassword, false)
  380. if err != nil {
  381. t.Fatal(err)
  382. }
  383. categoryName := "My category"
  384. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  385. _, err = client.CreateCategory(categoryName)
  386. if err != nil {
  387. t.Fatal(err)
  388. }
  389. categories, err := client.Categories()
  390. if err != nil {
  391. t.Fatal(err)
  392. }
  393. if len(categories) != 2 {
  394. t.Fatalf(`Invalid number of categories, got "%v" instead of "%v"`, len(categories), 2)
  395. }
  396. if categories[0].ID == 0 {
  397. t.Fatalf(`Invalid categoryID, got "%v"`, categories[0].ID)
  398. }
  399. if categories[0].UserID != user.ID {
  400. t.Fatalf(`Invalid userID, got "%v" instead of "%v"`, categories[0].UserID, user.ID)
  401. }
  402. if categories[0].Title != "All" {
  403. t.Fatalf(`Invalid title, got "%v" instead of "%v"`, categories[0].Title, "All")
  404. }
  405. if categories[1].ID == 0 {
  406. t.Fatalf(`Invalid categoryID, got "%v"`, categories[0].ID)
  407. }
  408. if categories[1].UserID != user.ID {
  409. t.Fatalf(`Invalid userID, got "%v" instead of "%v"`, categories[1].UserID, user.ID)
  410. }
  411. if categories[1].Title != categoryName {
  412. t.Fatalf(`Invalid title, got "%v" instead of "%v"`, categories[1].Title, categoryName)
  413. }
  414. }
  415. func TestDeleteCategory(t *testing.T) {
  416. username := getRandomUsername()
  417. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  418. _, err := client.CreateUser(username, testStandardPassword, false)
  419. if err != nil {
  420. t.Fatal(err)
  421. }
  422. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  423. category, err := client.CreateCategory("My category")
  424. if err != nil {
  425. t.Fatal(err)
  426. }
  427. err = client.DeleteCategory(category.ID)
  428. if err != nil {
  429. t.Fatal(`Removing a category should not raise any error`)
  430. }
  431. }
  432. func TestCannotDeleteCategoryOfAnotherUser(t *testing.T) {
  433. username := getRandomUsername()
  434. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  435. categories, err := client.Categories()
  436. if err != nil {
  437. t.Fatal(err)
  438. }
  439. _, err = client.CreateUser(username, testStandardPassword, false)
  440. if err != nil {
  441. t.Fatal(err)
  442. }
  443. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  444. err = client.DeleteCategory(categories[0].ID)
  445. if err == nil {
  446. t.Fatal(`Removing a category that belongs to another user should be forbidden`)
  447. }
  448. }
  449. func TestDiscoverSubscriptions(t *testing.T) {
  450. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  451. subscriptions, err := client.Discover(testWebsiteURL)
  452. if err != nil {
  453. t.Fatal(err)
  454. }
  455. if len(subscriptions) != 1 {
  456. t.Fatalf(`Invalid number of subscriptions, got "%v" instead of "%v"`, len(subscriptions), 2)
  457. }
  458. if subscriptions[0].Title != testFeedTitle {
  459. t.Fatalf(`Invalid feed title, got "%v" instead of "%v"`, subscriptions[0].Title, testFeedTitle)
  460. }
  461. if subscriptions[0].Type != "atom" {
  462. t.Fatalf(`Invalid feed type, got "%v" instead of "%v"`, subscriptions[0].Type, "atom")
  463. }
  464. if subscriptions[0].URL != testFeedURL {
  465. t.Fatalf(`Invalid feed URL, got "%v" instead of "%v"`, subscriptions[0].URL, testFeedURL)
  466. }
  467. }
  468. func TestCreateFeed(t *testing.T) {
  469. username := getRandomUsername()
  470. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  471. _, err := client.CreateUser(username, testStandardPassword, false)
  472. if err != nil {
  473. t.Fatal(err)
  474. }
  475. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  476. categories, err := client.Categories()
  477. if err != nil {
  478. t.Fatal(err)
  479. }
  480. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  481. if err != nil {
  482. t.Fatal(err)
  483. }
  484. if feedID == 0 {
  485. t.Fatalf(`Invalid feed ID, got "%v"`, feedID)
  486. }
  487. }
  488. func TestCannotCreateDuplicatedFeed(t *testing.T) {
  489. username := getRandomUsername()
  490. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  491. _, err := client.CreateUser(username, testStandardPassword, false)
  492. if err != nil {
  493. t.Fatal(err)
  494. }
  495. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  496. categories, err := client.Categories()
  497. if err != nil {
  498. t.Fatal(err)
  499. }
  500. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  501. if err != nil {
  502. t.Fatal(err)
  503. }
  504. if feedID == 0 {
  505. t.Fatalf(`Invalid feed ID, got "%v"`, feedID)
  506. }
  507. _, err = client.CreateFeed(testFeedURL, categories[0].ID)
  508. if err == nil {
  509. t.Fatal(`Duplicated feeds should not be allowed`)
  510. }
  511. }
  512. func TestCreateFeedWithInexistingCategory(t *testing.T) {
  513. username := getRandomUsername()
  514. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  515. _, err := client.CreateUser(username, testStandardPassword, false)
  516. if err != nil {
  517. t.Fatal(err)
  518. }
  519. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  520. _, err = client.CreateFeed(testFeedURL, -1)
  521. if err == nil {
  522. t.Fatal(`Feeds should not be created with inexisting category`)
  523. }
  524. }
  525. func TestExport(t *testing.T) {
  526. username := getRandomUsername()
  527. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  528. _, err := client.CreateUser(username, testStandardPassword, false)
  529. if err != nil {
  530. t.Fatal(err)
  531. }
  532. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  533. output, err := client.Export()
  534. if err != nil {
  535. t.Fatal(err)
  536. }
  537. if !strings.HasPrefix(string(output), "<?xml") {
  538. t.Fatalf(`Invalid OPML export, got "%s"`, string(output))
  539. }
  540. }
  541. func TestImport(t *testing.T) {
  542. username := getRandomUsername()
  543. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  544. _, err := client.CreateUser(username, testStandardPassword, false)
  545. if err != nil {
  546. t.Fatal(err)
  547. }
  548. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  549. data := `<?xml version="1.0" encoding="UTF-8"?>
  550. <opml version="2.0">
  551. <body>
  552. <outline text="Test Category">
  553. <outline title="Test" text="Test" xmlUrl="` + testFeedURL + `" htmlUrl="` + testWebsiteURL + `"></outline>
  554. </outline>
  555. </body>
  556. </opml>`
  557. b := bytes.NewReader([]byte(data))
  558. err = client.Import(ioutil.NopCloser(b))
  559. if err != nil {
  560. t.Fatal(err)
  561. }
  562. }
  563. func TestUpdateFeed(t *testing.T) {
  564. username := getRandomUsername()
  565. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  566. _, err := client.CreateUser(username, testStandardPassword, false)
  567. if err != nil {
  568. t.Fatal(err)
  569. }
  570. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  571. categories, err := client.Categories()
  572. if err != nil {
  573. t.Fatal(err)
  574. }
  575. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  576. if err != nil {
  577. t.Fatal(err)
  578. }
  579. if feedID == 0 {
  580. t.Fatalf(`Invalid feed ID, got "%v"`, feedID)
  581. }
  582. feed, err := client.Feed(feedID)
  583. if err != nil {
  584. t.Fatal(err)
  585. }
  586. newTitle := "My new feed"
  587. feed.Title = newTitle
  588. feed, err = client.UpdateFeed(feed)
  589. if err != nil {
  590. t.Fatal(err)
  591. }
  592. if feed.Title != newTitle {
  593. t.Errorf(`Wrong title, got "%v" instead of "%v"`, feed.Title, newTitle)
  594. }
  595. }
  596. func TestDeleteFeed(t *testing.T) {
  597. username := getRandomUsername()
  598. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  599. _, err := client.CreateUser(username, testStandardPassword, false)
  600. if err != nil {
  601. t.Fatal(err)
  602. }
  603. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  604. categories, err := client.Categories()
  605. if err != nil {
  606. t.Fatal(err)
  607. }
  608. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  609. if err != nil {
  610. t.Fatal(err)
  611. }
  612. err = client.DeleteFeed(feedID)
  613. if err != nil {
  614. t.Fatal(err)
  615. }
  616. }
  617. func TestRefreshFeed(t *testing.T) {
  618. username := getRandomUsername()
  619. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  620. _, err := client.CreateUser(username, testStandardPassword, false)
  621. if err != nil {
  622. t.Fatal(err)
  623. }
  624. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  625. categories, err := client.Categories()
  626. if err != nil {
  627. t.Fatal(err)
  628. }
  629. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  630. if err != nil {
  631. t.Fatal(err)
  632. }
  633. err = client.RefreshFeed(feedID)
  634. if err != nil {
  635. t.Fatal(err)
  636. }
  637. }
  638. func TestGetFeed(t *testing.T) {
  639. username := getRandomUsername()
  640. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  641. _, err := client.CreateUser(username, testStandardPassword, false)
  642. if err != nil {
  643. t.Fatal(err)
  644. }
  645. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  646. categories, err := client.Categories()
  647. if err != nil {
  648. t.Fatal(err)
  649. }
  650. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  651. if err != nil {
  652. t.Fatal(err)
  653. }
  654. feed, err := client.Feed(feedID)
  655. if err != nil {
  656. t.Fatal(err)
  657. }
  658. if feed.Title != testFeedTitle {
  659. t.Fatalf(`Invalid feed title, got "%v" instead of "%v"`, feed.Title, testFeedTitle)
  660. }
  661. if feed.SiteURL != testWebsiteURL {
  662. t.Fatalf(`Invalid site URL, got "%v" instead of "%v"`, feed.SiteURL, testWebsiteURL)
  663. }
  664. if feed.FeedURL != testFeedURL {
  665. t.Fatalf(`Invalid feed URL, got "%v" instead of "%v"`, feed.FeedURL, testFeedURL)
  666. }
  667. if feed.Category.ID != categories[0].ID {
  668. t.Fatalf(`Invalid feed category ID, got "%v" instead of "%v"`, feed.Category.ID, categories[0].ID)
  669. }
  670. if feed.Category.UserID != categories[0].UserID {
  671. t.Fatalf(`Invalid feed category user ID, got "%v" instead of "%v"`, feed.Category.UserID, categories[0].UserID)
  672. }
  673. if feed.Category.Title != categories[0].Title {
  674. t.Fatalf(`Invalid feed category title, got "%v" instead of "%v"`, feed.Category.Title, categories[0].Title)
  675. }
  676. }
  677. func TestGetFeedIcon(t *testing.T) {
  678. username := getRandomUsername()
  679. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  680. _, err := client.CreateUser(username, testStandardPassword, false)
  681. if err != nil {
  682. t.Fatal(err)
  683. }
  684. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  685. categories, err := client.Categories()
  686. if err != nil {
  687. t.Fatal(err)
  688. }
  689. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  690. if err != nil {
  691. t.Fatal(err)
  692. }
  693. feedIcon, err := client.FeedIcon(feedID)
  694. if err != nil {
  695. t.Fatal(err)
  696. }
  697. if feedIcon.ID == 0 {
  698. t.Fatalf(`Invalid feed icon ID, got "%v"`, feedIcon.ID)
  699. }
  700. if feedIcon.MimeType != "image/x-icon" {
  701. t.Fatalf(`Invalid feed icon mime type, got "%v" instead of "%v"`, feedIcon.MimeType, "image/x-icon")
  702. }
  703. if !strings.Contains(feedIcon.Data, "image/x-icon") {
  704. t.Fatalf(`Invalid feed icon data, got "%v"`, feedIcon.Data)
  705. }
  706. }
  707. func TestGetFeedIconNotFound(t *testing.T) {
  708. username := getRandomUsername()
  709. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  710. _, err := client.CreateUser(username, testStandardPassword, false)
  711. if err != nil {
  712. t.Fatal(err)
  713. }
  714. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  715. if _, err := client.FeedIcon(42); err == nil {
  716. t.Fatalf(`The feed icon should be null`)
  717. }
  718. }
  719. func TestGetFeeds(t *testing.T) {
  720. username := getRandomUsername()
  721. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  722. _, err := client.CreateUser(username, testStandardPassword, false)
  723. if err != nil {
  724. t.Fatal(err)
  725. }
  726. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  727. categories, err := client.Categories()
  728. if err != nil {
  729. t.Fatal(err)
  730. }
  731. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  732. if err != nil {
  733. t.Fatal(err)
  734. }
  735. feeds, err := client.Feeds()
  736. if err != nil {
  737. t.Fatal(err)
  738. }
  739. if len(feeds) != 1 {
  740. t.Fatalf(`Invalid number of feeds`)
  741. }
  742. if feeds[0].ID != feedID {
  743. t.Fatalf(`Invalid feed ID, got "%v" instead of "%v"`, feeds[0].ID, feedID)
  744. }
  745. if feeds[0].Title != testFeedTitle {
  746. t.Fatalf(`Invalid feed title, got "%v" instead of "%v"`, feeds[0].Title, testFeedTitle)
  747. }
  748. if feeds[0].SiteURL != testWebsiteURL {
  749. t.Fatalf(`Invalid site URL, got "%v" instead of "%v"`, feeds[0].SiteURL, testWebsiteURL)
  750. }
  751. if feeds[0].FeedURL != testFeedURL {
  752. t.Fatalf(`Invalid feed URL, got "%v" instead of "%v"`, feeds[0].FeedURL, testFeedURL)
  753. }
  754. if feeds[0].Category.ID != categories[0].ID {
  755. t.Fatalf(`Invalid feed category ID, got "%v" instead of "%v"`, feeds[0].Category.ID, categories[0].ID)
  756. }
  757. if feeds[0].Category.UserID != categories[0].UserID {
  758. t.Fatalf(`Invalid feed category user ID, got "%v" instead of "%v"`, feeds[0].Category.UserID, categories[0].UserID)
  759. }
  760. if feeds[0].Category.Title != categories[0].Title {
  761. t.Fatalf(`Invalid feed category title, got "%v" instead of "%v"`, feeds[0].Category.Title, categories[0].Title)
  762. }
  763. }
  764. func TestGetAllFeedEntries(t *testing.T) {
  765. username := getRandomUsername()
  766. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  767. _, err := client.CreateUser(username, testStandardPassword, false)
  768. if err != nil {
  769. t.Fatal(err)
  770. }
  771. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  772. categories, err := client.Categories()
  773. if err != nil {
  774. t.Fatal(err)
  775. }
  776. feedID, err := client.CreateFeed(testFeedURL, categories[0].ID)
  777. if err != nil {
  778. t.Fatal(err)
  779. }
  780. allResults, err := client.FeedEntries(feedID, nil)
  781. if err != nil {
  782. t.Fatal(err)
  783. }
  784. if allResults.Total == 0 {
  785. t.Fatal(`Invalid number of entries`)
  786. }
  787. if allResults.Entries[0].Title == "" {
  788. t.Fatal(`Invalid entry title`)
  789. }
  790. filteredResults, err := client.FeedEntries(feedID, &miniflux.Filter{Limit: 1, Offset: 5})
  791. if err != nil {
  792. t.Fatal(err)
  793. }
  794. if allResults.Total != filteredResults.Total {
  795. t.Fatal(`Total should always contains the total number of items regardless of filters`)
  796. }
  797. if allResults.Entries[0].ID == filteredResults.Entries[0].ID {
  798. t.Fatal(`Filtered entries should be different than previous result`)
  799. }
  800. }
  801. func TestGetAllEntries(t *testing.T) {
  802. username := getRandomUsername()
  803. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  804. _, err := client.CreateUser(username, testStandardPassword, false)
  805. if err != nil {
  806. t.Fatal(err)
  807. }
  808. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  809. categories, err := client.Categories()
  810. if err != nil {
  811. t.Fatal(err)
  812. }
  813. _, err = client.CreateFeed(testFeedURL, categories[0].ID)
  814. if err != nil {
  815. t.Fatal(err)
  816. }
  817. resultWithoutSorting, err := client.Entries(nil)
  818. if err != nil {
  819. t.Fatal(err)
  820. }
  821. if resultWithoutSorting.Total == 0 {
  822. t.Fatal(`Invalid number of entries`)
  823. }
  824. resultWithStatusFilter, err := client.Entries(&miniflux.Filter{Status: miniflux.EntryStatusRead})
  825. if err != nil {
  826. t.Fatal(err)
  827. }
  828. if resultWithStatusFilter.Total != 0 {
  829. t.Fatal(`We should have 0 read entries`)
  830. }
  831. resultWithDifferentSorting, err := client.Entries(&miniflux.Filter{Order: "published_at", Direction: "desc"})
  832. if err != nil {
  833. t.Fatal(err)
  834. }
  835. if resultWithDifferentSorting.Entries[0].Title == resultWithoutSorting.Entries[0].Title {
  836. t.Fatalf(`The items should be sorted differently "%v" vs "%v"`, resultWithDifferentSorting.Entries[0].Title, resultWithoutSorting.Entries[0].Title)
  837. }
  838. }
  839. func TestInvalidFilters(t *testing.T) {
  840. username := getRandomUsername()
  841. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  842. _, err := client.CreateUser(username, testStandardPassword, false)
  843. if err != nil {
  844. t.Fatal(err)
  845. }
  846. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  847. categories, err := client.Categories()
  848. if err != nil {
  849. t.Fatal(err)
  850. }
  851. _, err = client.CreateFeed(testFeedURL, categories[0].ID)
  852. if err != nil {
  853. t.Fatal(err)
  854. }
  855. _, err = client.Entries(&miniflux.Filter{Status: "invalid"})
  856. if err == nil {
  857. t.Fatal(`Using invalid status should raise an error`)
  858. }
  859. _, err = client.Entries(&miniflux.Filter{Direction: "invalid"})
  860. if err == nil {
  861. t.Fatal(`Using invalid direction should raise an error`)
  862. }
  863. _, err = client.Entries(&miniflux.Filter{Order: "invalid"})
  864. if err == nil {
  865. t.Fatal(`Using invalid order should raise an error`)
  866. }
  867. }
  868. func TestGetEntry(t *testing.T) {
  869. username := getRandomUsername()
  870. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  871. _, err := client.CreateUser(username, testStandardPassword, false)
  872. if err != nil {
  873. t.Fatal(err)
  874. }
  875. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  876. categories, err := client.Categories()
  877. if err != nil {
  878. t.Fatal(err)
  879. }
  880. _, err = client.CreateFeed(testFeedURL, categories[0].ID)
  881. if err != nil {
  882. t.Fatal(err)
  883. }
  884. result, err := client.Entries(&miniflux.Filter{Limit: 1})
  885. if err != nil {
  886. t.Fatal(err)
  887. }
  888. entry, err := client.FeedEntry(result.Entries[0].FeedID, result.Entries[0].ID)
  889. if err != nil {
  890. t.Fatal(err)
  891. }
  892. if entry.ID != result.Entries[0].ID {
  893. t.Fatal("Wrong entry returned")
  894. }
  895. entry, err = client.Entry(result.Entries[0].ID)
  896. if err != nil {
  897. t.Fatal(err)
  898. }
  899. if entry.ID != result.Entries[0].ID {
  900. t.Fatal("Wrong entry returned")
  901. }
  902. }
  903. func TestUpdateStatus(t *testing.T) {
  904. username := getRandomUsername()
  905. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  906. _, err := client.CreateUser(username, testStandardPassword, false)
  907. if err != nil {
  908. t.Fatal(err)
  909. }
  910. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  911. categories, err := client.Categories()
  912. if err != nil {
  913. t.Fatal(err)
  914. }
  915. _, err = client.CreateFeed(testFeedURL, categories[0].ID)
  916. if err != nil {
  917. t.Fatal(err)
  918. }
  919. result, err := client.Entries(&miniflux.Filter{Limit: 1})
  920. if err != nil {
  921. t.Fatal(err)
  922. }
  923. err = client.UpdateEntries([]int64{result.Entries[0].ID}, miniflux.EntryStatusRead)
  924. if err != nil {
  925. t.Fatal(err)
  926. }
  927. entry, err := client.Entry(result.Entries[0].ID)
  928. if err != nil {
  929. t.Fatal(err)
  930. }
  931. if entry.Status != miniflux.EntryStatusRead {
  932. t.Fatal("The entry status should be updated")
  933. }
  934. err = client.UpdateEntries([]int64{result.Entries[0].ID}, "invalid")
  935. if err == nil {
  936. t.Fatal(`Invalid entry status should ne be accepted`)
  937. }
  938. }
  939. func TestToggleBookmark(t *testing.T) {
  940. username := getRandomUsername()
  941. client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
  942. _, err := client.CreateUser(username, testStandardPassword, false)
  943. if err != nil {
  944. t.Fatal(err)
  945. }
  946. client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
  947. categories, err := client.Categories()
  948. if err != nil {
  949. t.Fatal(err)
  950. }
  951. _, err = client.CreateFeed(testFeedURL, categories[0].ID)
  952. if err != nil {
  953. t.Fatal(err)
  954. }
  955. result, err := client.Entries(&miniflux.Filter{Limit: 1})
  956. if err != nil {
  957. t.Fatal(err)
  958. }
  959. if result.Entries[0].Starred {
  960. t.Fatal("The entry should not be starred")
  961. }
  962. err = client.ToggleBookmark(result.Entries[0].ID)
  963. if err != nil {
  964. t.Fatal(err)
  965. }
  966. entry, err := client.Entry(result.Entries[0].ID)
  967. if err != nil {
  968. t.Fatal(err)
  969. }
  970. if !entry.Starred {
  971. t.Fatal("The entry should be starred")
  972. }
  973. }
  974. func getRandomUsername() string {
  975. rand.Seed(time.Now().UnixNano())
  976. var suffix []string
  977. for i := 0; i < 10; i++ {
  978. suffix = append(suffix, strconv.Itoa(rand.Intn(1000)))
  979. }
  980. return "user" + strings.Join(suffix, "")
  981. }