1
0

integration_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. package graph
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "strings"
  6. "testing"
  7. "github.com/99designs/gqlgen/client"
  8. "github.com/99designs/gqlgen/graphql/handler"
  9. "github.com/bradleyjkemp/cupaloy/v2"
  10. "gogs.dmsc.dev/arp/graph/testutil"
  11. "gorm.io/gorm"
  12. )
  13. var snapshotter = cupaloy.New(cupaloy.SnapshotSubdirectory("testdata/snapshots"))
  14. type TestClient struct {
  15. client *client.Client
  16. db *gorm.DB
  17. }
  18. type IDTracker struct {
  19. Permissions map[string]string
  20. Roles map[string]string
  21. Users map[string]string
  22. TaskStatuses map[string]string
  23. Services map[string]string
  24. Tasks map[string]string
  25. Notes map[string]string
  26. Channels []string
  27. Messages []string
  28. }
  29. func NewIDTracker() *IDTracker {
  30. return &IDTracker{
  31. Permissions: make(map[string]string),
  32. Roles: make(map[string]string),
  33. Users: make(map[string]string),
  34. TaskStatuses: make(map[string]string),
  35. Services: make(map[string]string),
  36. Tasks: make(map[string]string),
  37. Notes: make(map[string]string),
  38. Channels: make([]string, 0),
  39. Messages: make([]string, 0),
  40. }
  41. }
  42. func setupTestClient(t *testing.T) (*TestClient, *IDTracker) {
  43. db, err := testutil.SetupTestDB()
  44. if err != nil {
  45. t.Fatalf("Failed to setup test database: %v", err)
  46. }
  47. resolver := &Resolver{DB: db}
  48. schema := NewExecutableSchema(Config{Resolvers: resolver})
  49. srv := handler.NewDefaultServer(schema)
  50. return &TestClient{client: client.New(srv), db: db}, NewIDTracker()
  51. }
  52. func normalizeJSON(jsonStr string) string {
  53. var data interface{}
  54. if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
  55. return jsonStr
  56. }
  57. normalizeData(data)
  58. bytes, _ := json.MarshalIndent(data, "", " ")
  59. return string(bytes)
  60. }
  61. func normalizeData(data interface{}) {
  62. switch v := data.(type) {
  63. case map[string]interface{}:
  64. delete(v, "id")
  65. delete(v, "ID")
  66. delete(v, "createdAt")
  67. delete(v, "updatedAt")
  68. delete(v, "sentAt")
  69. delete(v, "createdByID")
  70. delete(v, "userId")
  71. delete(v, "serviceId")
  72. delete(v, "statusId")
  73. delete(v, "assigneeId")
  74. delete(v, "conversationId")
  75. delete(v, "senderId")
  76. for _, val := range v {
  77. normalizeData(val)
  78. }
  79. case []interface{}:
  80. for _, item := range v {
  81. normalizeData(item)
  82. }
  83. }
  84. }
  85. func snapshotResult(t *testing.T, name string, jsonStr string) {
  86. normalized := normalizeJSON(jsonStr)
  87. snapshotter.SnapshotT(t, name, normalized)
  88. }
  89. func TestIntegration_Bootstrap(t *testing.T) {
  90. tc, tracker := setupTestClient(t)
  91. seed := testutil.GetSeedData()
  92. // Phase 1: Create Permissions
  93. t.Run("CreatePermissions", func(t *testing.T) {
  94. for _, perm := range seed.Permissions {
  95. var response struct {
  96. CreatePermission struct {
  97. ID string `json:"id"`
  98. Code string `json:"code"`
  99. Description string `json:"description"`
  100. } `json:"createPermission"`
  101. }
  102. query := fmt.Sprintf(`mutation { createPermission(input: {code: "%s", description: "%s"}) { id code description } }`, perm.Code, perm.Description)
  103. err := tc.client.Post(query, &response)
  104. if err != nil {
  105. t.Fatalf("Failed to create permission %s: %v", perm.Code, err)
  106. }
  107. tracker.Permissions[perm.Code] = response.CreatePermission.ID
  108. }
  109. var permsResponse struct {
  110. Permissions []interface{} `json:"permissions"`
  111. }
  112. tc.client.Post(`query { permissions { id code description } }`, &permsResponse)
  113. jsonBytes, _ := json.MarshalIndent(permsResponse, "", " ")
  114. snapshotResult(t, "permissions", string(jsonBytes))
  115. })
  116. // Phase 2: Create Roles
  117. t.Run("CreateRoles", func(t *testing.T) {
  118. for _, role := range seed.Roles {
  119. permIDs := make([]string, len(role.PermissionCodes))
  120. for i, code := range role.PermissionCodes {
  121. permIDs[i] = tracker.Permissions[code]
  122. }
  123. var response struct {
  124. CreateRole struct {
  125. ID string `json:"id"`
  126. Name string `json:"name"`
  127. Description string `json:"description"`
  128. } `json:"createRole"`
  129. }
  130. query := fmt.Sprintf(`mutation { createRole(input: {name: "%s", description: "%s", permissions: ["%s"]}) { id name description } }`, role.Name, role.Description, strings.Join(permIDs, `", "`))
  131. err := tc.client.Post(query, &response)
  132. if err != nil {
  133. t.Fatalf("Failed to create role %s: %v", role.Name, err)
  134. }
  135. tracker.Roles[role.Name] = response.CreateRole.ID
  136. }
  137. var rolesResponse struct {
  138. Roles []interface{} `json:"roles"`
  139. }
  140. tc.client.Post(`query { roles { id name description permissions { id code } } }`, &rolesResponse)
  141. jsonBytes, _ := json.MarshalIndent(rolesResponse, "", " ")
  142. snapshotResult(t, "roles", string(jsonBytes))
  143. })
  144. // Phase 3: Create Users
  145. t.Run("CreateUsers", func(t *testing.T) {
  146. for _, user := range seed.Users {
  147. roleIDs := make([]string, len(user.RoleNames))
  148. for i, name := range user.RoleNames {
  149. roleIDs[i] = tracker.Roles[name]
  150. }
  151. var response struct {
  152. CreateUser struct {
  153. ID string `json:"id"`
  154. Email string `json:"email"`
  155. } `json:"createUser"`
  156. }
  157. query := fmt.Sprintf(`mutation { createUser(input: {email: "%s", password: "%s", roles: ["%s"]}) { id email } }`, user.Email, user.Password, strings.Join(roleIDs, `", "`))
  158. err := tc.client.Post(query, &response)
  159. if err != nil {
  160. t.Fatalf("Failed to create user %s: %v", user.Email, err)
  161. }
  162. tracker.Users[user.Email] = response.CreateUser.ID
  163. }
  164. var usersResponse struct {
  165. Users []interface{} `json:"users"`
  166. }
  167. tc.client.Post(`query { users { id email roles { id name } } }`, &usersResponse)
  168. jsonBytes, _ := json.MarshalIndent(usersResponse, "", " ")
  169. snapshotResult(t, "users", string(jsonBytes))
  170. })
  171. // Phase 4: Create Task Statuses
  172. t.Run("CreateTaskStatuses", func(t *testing.T) {
  173. for _, status := range seed.TaskStatuses {
  174. var response struct {
  175. CreateTaskStatus struct {
  176. ID string `json:"id"`
  177. Code string `json:"code"`
  178. Label string `json:"label"`
  179. } `json:"createTaskStatus"`
  180. }
  181. query := fmt.Sprintf(`mutation { createTaskStatus(input: {code: "%s", label: "%s"}) { id code label } }`, status.Code, status.Label)
  182. err := tc.client.Post(query, &response)
  183. if err != nil {
  184. t.Fatalf("Failed to create task status %s: %v", status.Code, err)
  185. }
  186. tracker.TaskStatuses[status.Code] = response.CreateTaskStatus.ID
  187. }
  188. var statusesResponse struct {
  189. TaskStatuses []interface{} `json:"taskStatuses"`
  190. }
  191. tc.client.Post(`query { taskStatuses { id code label } }`, &statusesResponse)
  192. jsonBytes, _ := json.MarshalIndent(statusesResponse, "", " ")
  193. snapshotResult(t, "taskStatuses", string(jsonBytes))
  194. })
  195. // Phase 5: Create Services
  196. t.Run("CreateServices", func(t *testing.T) {
  197. for _, service := range seed.Services {
  198. participantIDs := make([]string, len(service.ParticipantEmails))
  199. for i, email := range service.ParticipantEmails {
  200. participantIDs[i] = tracker.Users[email]
  201. }
  202. var response struct {
  203. CreateService struct {
  204. ID string `json:"id"`
  205. Name string `json:"name"`
  206. } `json:"createService"`
  207. }
  208. query := fmt.Sprintf(`mutation { createService(input: {name: "%s", description: "%s", createdById: "%s", participants: ["%s"]}) { id name } }`, service.Name, service.Description, tracker.Users[service.CreatorEmail], strings.Join(participantIDs, `", "`))
  209. err := tc.client.Post(query, &response)
  210. if err != nil {
  211. t.Fatalf("Failed to create service %s: %v", service.Name, err)
  212. }
  213. tracker.Services[service.Name] = response.CreateService.ID
  214. }
  215. var servicesResponse struct {
  216. Services []interface{} `json:"services"`
  217. }
  218. tc.client.Post(`query { services { id name description } }`, &servicesResponse)
  219. jsonBytes, _ := json.MarshalIndent(servicesResponse, "", " ")
  220. snapshotResult(t, "services", string(jsonBytes))
  221. })
  222. // Phase 6: Create Tasks
  223. t.Run("CreateTasks", func(t *testing.T) {
  224. for _, task := range seed.Tasks {
  225. var response struct {
  226. CreateTask struct {
  227. ID string `json:"id"`
  228. Title string `json:"title"`
  229. } `json:"createTask"`
  230. }
  231. var assigneeID string
  232. if task.AssigneeEmail != "" {
  233. assigneeID = tracker.Users[task.AssigneeEmail]
  234. }
  235. statusID := tracker.TaskStatuses[task.StatusCode]
  236. if assigneeID != "" {
  237. query := fmt.Sprintf(`mutation { createTask(input: {title: "%s", content: "%s", createdById: "%s", assigneeId: "%s", statusId: "%s", priority: "%s"}) { id title } }`, task.Title, task.Content, tracker.Users[task.CreatorEmail], assigneeID, statusID, task.Priority)
  238. err := tc.client.Post(query, &response)
  239. if err != nil {
  240. t.Fatalf("Failed to create task %s: %v", task.Title, err)
  241. }
  242. } else {
  243. query := fmt.Sprintf(`mutation { createTask(input: {title: "%s", content: "%s", createdById: "%s", statusId: "%s", priority: "%s"}) { id title } }`, task.Title, task.Content, tracker.Users[task.CreatorEmail], statusID, task.Priority)
  244. err := tc.client.Post(query, &response)
  245. if err != nil {
  246. t.Fatalf("Failed to create task %s: %v", task.Title, err)
  247. }
  248. }
  249. tracker.Tasks[task.Title] = response.CreateTask.ID
  250. }
  251. var tasksResponse struct {
  252. Tasks []interface{} `json:"tasks"`
  253. }
  254. tc.client.Post(`query { tasks { id title content priority } }`, &tasksResponse)
  255. jsonBytes, _ := json.MarshalIndent(tasksResponse, "", " ")
  256. snapshotResult(t, "tasks", string(jsonBytes))
  257. })
  258. // Phase 7: Create Notes
  259. t.Run("CreateNotes", func(t *testing.T) {
  260. for _, note := range seed.Notes {
  261. var response struct {
  262. CreateNote struct {
  263. ID string `json:"id"`
  264. Title string `json:"title"`
  265. } `json:"createNote"`
  266. }
  267. query := fmt.Sprintf(`mutation { createNote(input: {title: "%s", content: "%s", userId: "%s", serviceId: "%s"}) { id title } }`, note.Title, note.Content, tracker.Users[note.UserEmail], tracker.Services[note.ServiceName])
  268. err := tc.client.Post(query, &response)
  269. if err != nil {
  270. t.Fatalf("Failed to create note %s: %v", note.Title, err)
  271. }
  272. tracker.Notes[note.Title] = response.CreateNote.ID
  273. }
  274. var notesResponse struct {
  275. Notes []interface{} `json:"notes"`
  276. }
  277. tc.client.Post(`query { notes { id title content } }`, &notesResponse)
  278. jsonBytes, _ := json.MarshalIndent(notesResponse, "", " ")
  279. snapshotResult(t, "notes", string(jsonBytes))
  280. })
  281. // Phase 8: Create Channels
  282. t.Run("CreateChannels", func(t *testing.T) {
  283. for _, channel := range seed.Channels {
  284. participantIDs := make([]string, len(channel.ParticipantEmails))
  285. for i, email := range channel.ParticipantEmails {
  286. participantIDs[i] = tracker.Users[email]
  287. }
  288. var response struct {
  289. CreateChannel struct {
  290. ID string `json:"id"`
  291. } `json:"createChannel"`
  292. }
  293. query := fmt.Sprintf(`mutation { createChannel(input: {participants: ["%s"]}) { id } }`, strings.Join(participantIDs, `", "`))
  294. err := tc.client.Post(query, &response)
  295. if err != nil {
  296. t.Fatalf("Failed to create channel: %v", err)
  297. }
  298. tracker.Channels = append(tracker.Channels, response.CreateChannel.ID)
  299. }
  300. var channelsResponse struct {
  301. Channels []interface{} `json:"channels"`
  302. }
  303. tc.client.Post(`query { channels { id } }`, &channelsResponse)
  304. jsonBytes, _ := json.MarshalIndent(channelsResponse, "", " ")
  305. snapshotResult(t, "channels", string(jsonBytes))
  306. })
  307. // Phase 9: Create Messages
  308. t.Run("CreateMessages", func(t *testing.T) {
  309. for _, msg := range seed.Messages {
  310. var response struct {
  311. CreateMessage struct {
  312. ID string `json:"id"`
  313. } `json:"createMessage"`
  314. }
  315. query := fmt.Sprintf(`mutation { createMessage(input: {conversationId: "%s", senderId: "%s", content: "%s"}) { id } }`, tracker.Channels[msg.ChannelIndex], tracker.Users[msg.SenderEmail], msg.Content)
  316. err := tc.client.Post(query, &response)
  317. if err != nil {
  318. t.Fatalf("Failed to create message: %v", err)
  319. }
  320. tracker.Messages = append(tracker.Messages, response.CreateMessage.ID)
  321. }
  322. var messagesResponse struct {
  323. Messages []interface{} `json:"messages"`
  324. }
  325. tc.client.Post(`query { messages { id content } }`, &messagesResponse)
  326. jsonBytes, _ := json.MarshalIndent(messagesResponse, "", " ")
  327. snapshotResult(t, "messages", string(jsonBytes))
  328. })
  329. }
  330. // TestIntegration_Update tests update operations
  331. func TestIntegration_Update(t *testing.T) {
  332. tc, tracker := setupTestClient(t)
  333. seed := testutil.GetSeedData()
  334. // Bootstrap first
  335. bootstrapData(t, tc, tracker, seed)
  336. // Update a user
  337. t.Run("UpdateUser", func(t *testing.T) {
  338. userID := tracker.Users["admin@example.com"]
  339. var response struct {
  340. UpdateUser struct {
  341. ID string `json:"id"`
  342. Email string `json:"email"`
  343. } `json:"updateUser"`
  344. }
  345. query := fmt.Sprintf(`mutation { updateUser(id: "%s", input: {email: "admin-updated@example.com", password: "new-password", roles: ["%s"]}) { id email } }`, userID, tracker.Roles["admin"])
  346. err := tc.client.Post(query, &response)
  347. if err != nil {
  348. t.Fatalf("Failed to update user: %v", err)
  349. }
  350. var usersResponse struct {
  351. Users []interface{} `json:"users"`
  352. }
  353. tc.client.Post(`query { users { id email roles { id name } } }`, &usersResponse)
  354. jsonBytes, _ := json.MarshalIndent(usersResponse, "", " ")
  355. snapshotResult(t, "users_after_update", string(jsonBytes))
  356. })
  357. // Update a task
  358. t.Run("UpdateTask", func(t *testing.T) {
  359. taskID := tracker.Tasks["Setup development environment"]
  360. var response struct {
  361. UpdateTask struct {
  362. ID string `json:"id"`
  363. Title string `json:"title"`
  364. } `json:"updateTask"`
  365. }
  366. query := fmt.Sprintf(`mutation { updateTask(id: "%s", input: {title: "Setup development environment - COMPLETE", priority: "low"}) { id title } }`, taskID)
  367. err := tc.client.Post(query, &response)
  368. if err != nil {
  369. t.Fatalf("Failed to update task: %v", err)
  370. }
  371. var tasksResponse struct {
  372. Tasks []interface{} `json:"tasks"`
  373. }
  374. tc.client.Post(`query { tasks { id title content priority } }`, &tasksResponse)
  375. jsonBytes, _ := json.MarshalIndent(tasksResponse, "", " ")
  376. snapshotResult(t, "tasks_after_update", string(jsonBytes))
  377. })
  378. }
  379. // TestIntegration_Delete tests delete operations
  380. func TestIntegration_Delete(t *testing.T) {
  381. tc, tracker := setupTestClient(t)
  382. seed := testutil.GetSeedData()
  383. // Bootstrap first
  384. bootstrapData(t, tc, tracker, seed)
  385. // Delete a note
  386. t.Run("DeleteNote", func(t *testing.T) {
  387. noteID := tracker.Notes["Meeting notes - Sprint 1"]
  388. var response struct {
  389. DeleteNote bool `json:"deleteNote"`
  390. }
  391. query := fmt.Sprintf(`mutation { deleteNote(id: "%s") }`, noteID)
  392. err := tc.client.Post(query, &response)
  393. if err != nil {
  394. t.Fatalf("Failed to delete note: %v", err)
  395. }
  396. var notesResponse struct {
  397. Notes []interface{} `json:"notes"`
  398. }
  399. tc.client.Post(`query { notes { id title content } }`, &notesResponse)
  400. jsonBytes, _ := json.MarshalIndent(notesResponse, "", " ")
  401. snapshotResult(t, "notes_after_delete", string(jsonBytes))
  402. })
  403. // Delete a task
  404. t.Run("DeleteTask", func(t *testing.T) {
  405. taskID := tracker.Tasks["Performance optimization"]
  406. var response struct {
  407. DeleteTask bool `json:"deleteTask"`
  408. }
  409. query := fmt.Sprintf(`mutation { deleteTask(id: "%s") }`, taskID)
  410. err := tc.client.Post(query, &response)
  411. if err != nil {
  412. t.Fatalf("Failed to delete task: %v", err)
  413. }
  414. var tasksResponse struct {
  415. Tasks []interface{} `json:"tasks"`
  416. }
  417. tc.client.Post(`query { tasks { id title content priority } }`, &tasksResponse)
  418. jsonBytes, _ := json.MarshalIndent(tasksResponse, "", " ")
  419. snapshotResult(t, "tasks_after_delete", string(jsonBytes))
  420. })
  421. }
  422. // bootstrapData creates all entities for testing
  423. func bootstrapData(t *testing.T, tc *TestClient, tracker *IDTracker, seed testutil.SeedData) {
  424. // Create Permissions
  425. for _, perm := range seed.Permissions {
  426. var response struct {
  427. CreatePermission struct {
  428. ID string `json:"id"`
  429. } `json:"createPermission"`
  430. }
  431. query := fmt.Sprintf(`mutation { createPermission(input: {code: "%s", description: "%s"}) { id } }`, perm.Code, perm.Description)
  432. err := tc.client.Post(query, &response)
  433. if err != nil {
  434. t.Fatalf("Failed to create permission %s: %v", perm.Code, err)
  435. }
  436. tracker.Permissions[perm.Code] = response.CreatePermission.ID
  437. }
  438. // Create Roles
  439. for _, role := range seed.Roles {
  440. permIDs := make([]string, len(role.PermissionCodes))
  441. for i, code := range role.PermissionCodes {
  442. permIDs[i] = tracker.Permissions[code]
  443. }
  444. var response struct {
  445. CreateRole struct {
  446. ID string `json:"id"`
  447. } `json:"createRole"`
  448. }
  449. query := fmt.Sprintf(`mutation { createRole(input: {name: "%s", description: "%s", permissions: ["%s"]}) { id } }`, role.Name, role.Description, strings.Join(permIDs, `", "`))
  450. err := tc.client.Post(query, &response)
  451. if err != nil {
  452. t.Fatalf("Failed to create role %s: %v", role.Name, err)
  453. }
  454. tracker.Roles[role.Name] = response.CreateRole.ID
  455. }
  456. // Create Users
  457. for _, user := range seed.Users {
  458. roleIDs := make([]string, len(user.RoleNames))
  459. for i, name := range user.RoleNames {
  460. roleIDs[i] = tracker.Roles[name]
  461. }
  462. var response struct {
  463. CreateUser struct {
  464. ID string `json:"id"`
  465. } `json:"createUser"`
  466. }
  467. query := fmt.Sprintf(`mutation { createUser(input: {email: "%s", password: "%s", roles: ["%s"]}) { id } }`, user.Email, user.Password, strings.Join(roleIDs, `", "`))
  468. err := tc.client.Post(query, &response)
  469. if err != nil {
  470. t.Fatalf("Failed to create user %s: %v", user.Email, err)
  471. }
  472. tracker.Users[user.Email] = response.CreateUser.ID
  473. }
  474. // Create Task Statuses
  475. for _, status := range seed.TaskStatuses {
  476. var response struct {
  477. CreateTaskStatus struct {
  478. ID string `json:"id"`
  479. } `json:"createTaskStatus"`
  480. }
  481. query := fmt.Sprintf(`mutation { createTaskStatus(input: {code: "%s", label: "%s"}) { id } }`, status.Code, status.Label)
  482. err := tc.client.Post(query, &response)
  483. if err != nil {
  484. t.Fatalf("Failed to create task status %s: %v", status.Code, err)
  485. }
  486. tracker.TaskStatuses[status.Code] = response.CreateTaskStatus.ID
  487. }
  488. // Create Services
  489. for _, service := range seed.Services {
  490. participantIDs := make([]string, len(service.ParticipantEmails))
  491. for i, email := range service.ParticipantEmails {
  492. participantIDs[i] = tracker.Users[email]
  493. }
  494. var response struct {
  495. CreateService struct {
  496. ID string `json:"id"`
  497. } `json:"createService"`
  498. }
  499. query := fmt.Sprintf(`mutation { createService(input: {name: "%s", description: "%s", createdById: "%s", participants: ["%s"]}) { id } }`, service.Name, service.Description, tracker.Users[service.CreatorEmail], strings.Join(participantIDs, `", "`))
  500. err := tc.client.Post(query, &response)
  501. if err != nil {
  502. t.Fatalf("Failed to create service %s: %v", service.Name, err)
  503. }
  504. tracker.Services[service.Name] = response.CreateService.ID
  505. }
  506. // Create Tasks
  507. for _, task := range seed.Tasks {
  508. var response struct {
  509. CreateTask struct {
  510. ID string `json:"id"`
  511. } `json:"createTask"`
  512. }
  513. statusID := tracker.TaskStatuses[task.StatusCode]
  514. if task.AssigneeEmail != "" {
  515. query := fmt.Sprintf(`mutation { createTask(input: {title: "%s", content: "%s", createdById: "%s", assigneeId: "%s", statusId: "%s", priority: "%s"}) { id } }`, task.Title, task.Content, tracker.Users[task.CreatorEmail], tracker.Users[task.AssigneeEmail], statusID, task.Priority)
  516. err := tc.client.Post(query, &response)
  517. if err != nil {
  518. t.Fatalf("Failed to create task %s: %v", task.Title, err)
  519. }
  520. } else {
  521. query := fmt.Sprintf(`mutation { createTask(input: {title: "%s", content: "%s", createdById: "%s", statusId: "%s", priority: "%s"}) { id } }`, task.Title, task.Content, tracker.Users[task.CreatorEmail], statusID, task.Priority)
  522. err := tc.client.Post(query, &response)
  523. if err != nil {
  524. t.Fatalf("Failed to create task %s: %v", task.Title, err)
  525. }
  526. }
  527. tracker.Tasks[task.Title] = response.CreateTask.ID
  528. }
  529. // Create Notes
  530. for _, note := range seed.Notes {
  531. var response struct {
  532. CreateNote struct {
  533. ID string `json:"id"`
  534. } `json:"createNote"`
  535. }
  536. query := fmt.Sprintf(`mutation { createNote(input: {title: "%s", content: "%s", userId: "%s", serviceId: "%s"}) { id } }`, note.Title, note.Content, tracker.Users[note.UserEmail], tracker.Services[note.ServiceName])
  537. err := tc.client.Post(query, &response)
  538. if err != nil {
  539. t.Fatalf("Failed to create note %s: %v", note.Title, err)
  540. }
  541. tracker.Notes[note.Title] = response.CreateNote.ID
  542. }
  543. // Create Channels
  544. for _, channel := range seed.Channels {
  545. participantIDs := make([]string, len(channel.ParticipantEmails))
  546. for i, email := range channel.ParticipantEmails {
  547. participantIDs[i] = tracker.Users[email]
  548. }
  549. var response struct {
  550. CreateChannel struct {
  551. ID string `json:"id"`
  552. } `json:"createChannel"`
  553. }
  554. query := fmt.Sprintf(`mutation { createChannel(input: {participants: ["%s"]}) { id } }`, strings.Join(participantIDs, `", "`))
  555. err := tc.client.Post(query, &response)
  556. if err != nil {
  557. t.Fatalf("Failed to create channel: %v", err)
  558. }
  559. tracker.Channels = append(tracker.Channels, response.CreateChannel.ID)
  560. }
  561. // Create Messages
  562. for _, msg := range seed.Messages {
  563. var response struct {
  564. CreateMessage struct {
  565. ID string `json:"id"`
  566. } `json:"createMessage"`
  567. }
  568. query := fmt.Sprintf(`mutation { createMessage(input: {conversationId: "%s", senderId: "%s", content: "%s"}) { id } }`, tracker.Channels[msg.ChannelIndex], tracker.Users[msg.SenderEmail], msg.Content)
  569. err := tc.client.Post(query, &response)
  570. if err != nil {
  571. t.Fatalf("Failed to create message: %v", err)
  572. }
  573. tracker.Messages = append(tracker.Messages, response.CreateMessage.ID)
  574. }
  575. }