func TestGroupChannelFirstCreation(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("While creating the new group channel for the first time", t, func() { Convey("user should be able to create group channel", func() { acc, err := models.CreateAccountInBothDbs() So(err, ShouldBeNil) groupName := models.RandomGroupName() ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) channel, err := rest.CreateChannelByGroupNameAndType( acc.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) So(channel.GroupName, ShouldEqual, groupName) }) }) }) }
func TestAccountFetchProfile(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("while fetching account activities in profile page", t, func() { account, _, groupName := models.CreateRandomGroupDataWithChecks() ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) // create channel channel, err := rest.CreateChannelByGroupNameAndType(account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId) So(err, ShouldBeNil) So(channel, ShouldNotBeNil) // create message post, err := rest.CreatePost(channel.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) Convey("it should list latest posts when there is no time interval in query", func() { cmc, err := rest.FetchAccountActivities(account.Id, ses.ClientId) So(err, ShouldBeNil) So(len(cmc), ShouldEqual, 1) So(cmc[0].Message.Body, ShouldEqual, post.Body) }) }) }) }
func TestCollaborationSesionEnd(t *testing.T) { r := runner.New("collaboration-tests") err := r.Init() if err != nil { panic(err) } defer r.Close() appConfig := config.MustRead(r.Conf.Path) modelhelper.Initialize(appConfig.Mongo) defer modelhelper.Close() Convey("while testing collaboration session end", t, func() { Convey("we should be able to create a doc on google drive", func() { Convey("we should be able to delete a created doc", func() { Convey("deleting an already deleted doc should not give error", func() { }) }) }) Convey("trying to delete a non-existing doc should not give error", func() { }) }) Convey("while pinging collaboration", t, func() { // owner owner, err := apimodels.CreateAccountInBothDbs() So(err, ShouldBeNil) So(owner, ShouldNotBeNil) groupName := apimodels.RandomGroupName() apimodels.CreateTypedGroupedChannelWithTest( owner.Id, apimodels.Channel_TYPE_GROUP, groupName, ) ownerSession, err := modelhelper.FetchOrCreateSession(owner.Nick, groupName) So(err, ShouldBeNil) So(ownerSession, ShouldNotBeNil) Convey("reponse should be success", func() { p := &models.Ping{ AccountId: 1, FileId: "hello", } res, err := rest.CollaborationPing(p, ownerSession.ClientId) So(err, ShouldBeNil) So(res, ShouldNotBeNil) }) }) }
func withStubData(endpoint string, f func(username string, groupName string, sessionID string)) { acc, _, groupName := models.CreateRandomGroupDataWithChecks() group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc.OldId), group.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) f(acc.Nick, groupName, ses.ClientId) }
func withStubData(f func(username string, groupName string, sessionID string)) { acc, _, groupName := models.CreateRandomGroupDataWithChecks() group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc.OldId), group.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) cus, err := EnsureCustomerForGroup(acc.Nick, groupName, &stripe.CustomerParams{}) tests.ResultedWithNoErrorCheck(cus, err) f(acc.Nick, groupName, ses.ClientId) err = DeleteCustomerForGroup(groupName) So(err, ShouldBeNil) }
func TestCheckOwnership(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("accounts can own things", t, func() { account, groupChannel, groupName := models.CreateRandomGroupDataWithChecks() ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) tedsAccount, err := models.CreateAccountInBothDbsWithNick("ted") tests.ResultedWithNoErrorCheck(tedsAccount, err) bobsPost, err := rest.CreatePost(groupChannel.Id, ses.ClientId) tests.ResultedWithNoErrorCheck(bobsPost, err) Convey("it should say when an account owns a post", func() { isOwner, err := rest.CheckPostOwnership(account, bobsPost) So(err, ShouldBeNil) So(isOwner, ShouldBeTrue) }) Convey("it should say when an account doesn't own a post", func() { isOwner, err := rest.CheckPostOwnership(tedsAccount, bobsPost) So(err, ShouldBeNil) So(isOwner, ShouldBeFalse) }) bobsChannel, err := rest.CreateChannelByGroupNameAndType(account.Id, groupName, models.Channel_TYPE_TOPIC, ses.ClientId) So(err, ShouldBeNil) Convey("it should say when an account owns a channel", func() { isOwner, err := rest.CheckChannelOwnership(account, bobsChannel) So(err, ShouldBeNil) So(isOwner, ShouldBeTrue) }) Convey("it should say when an account doesn't own a channel", func() { isOwner, err := rest.CheckChannelOwnership(tedsAccount, bobsChannel) So(err, ShouldBeNil) So(isOwner, ShouldBeFalse) }) }) }) }
func TestAccountGroupChannels(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("While fetching account activity count in profile page", t, func() { account, _, groupName := models.CreateRandomGroupDataWithChecks() ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) channel, err := rest.CreateChannelByGroupNameAndType(account.Id, groupName, models.Channel_TYPE_TOPIC, ses.ClientId) So(err, ShouldBeNil) So(channel, ShouldNotBeNil) cc, err := rest.FetchAccountChannels(ses.ClientId) So(err, ShouldBeNil) ccs := []models.ChannelContainer(*cc) So(len(ccs), ShouldEqual, 2) }) }) }
func TestStoreGetDeleteCredentials(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("While storing credentials", t, func() { Convey("after create account requirements", func() { ownerAccount, _, groupName := models.CreateRandomGroupDataWithChecks() ownerSes, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) So(ownerSes, ShouldNotBeNil) pathName := "testcredential" Convey("We should be able to store credentials", func() { keyValue := make(credential.KeyValue, 0) keyValue["test-key"] = "test-value" err := rest.StoreCredentialWithAuth(pathName, keyValue, ownerSes.ClientId) So(err, ShouldBeNil) }) Convey("We should be able to get credentials after storing", func() { res, err := rest.GetCredentialWithAuth(pathName, ownerSes.ClientId) So(err, ShouldBeNil) So(res, ShouldNotBeNil) So(res["test-key"], ShouldEqual, "test-value") }) Convey("We should be able to delete credentials after storing", func() { err := rest.DeleteCredentialWithAuth(pathName, ownerSes.ClientId) So(err, ShouldBeNil) }) Convey("We should not be able to get credentials after deletion process", func() { res, err := rest.GetCredentialWithAuth(pathName, ownerSes.ClientId) So(err.Error(), ShouldContainSubstring, "The specified key does not exist") So(res, ShouldBeNil) }) }) }) }) }
func withStubData(endpoint string, f func(username string, groupName string, sessionID string)) { createURL := endpoint + EndpointCustomerCreate acc, _, groupName := models.CreateRandomGroupDataWithChecks() group, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(group, err) err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc.OldId), group.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) req, err := json.Marshal(&stripe.CustomerParams{}) tests.ResultedWithNoErrorCheck(req, err) res, err := rest.DoRequestWithAuth("POST", createURL, req, ses.ClientId) tests.ResultedWithNoErrorCheck(res, err) f(acc.Nick, groupName, ses.ClientId) So(payment.DeleteCustomerForGroup(groupName), ShouldBeNil) }
func TestAccountProfilePostCount(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("While fetching account activity count in profile page", t, func() { account, _, groupName := models.CreateRandomGroupDataWithChecks() ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) // create channel channel, err := rest.CreateChannelByGroupNameAndType(account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId) So(err, ShouldBeNil) So(channel, ShouldNotBeNil) // create message post, err := rest.CreatePost(channel.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) Convey("it should fetch all post count when they are not troll", func() { cr, err := rest.FetchAccountActivityCount(account.Id, ses.ClientId) So(err, ShouldBeNil) So(cr, ShouldNotBeNil) So(cr.TotalCount, ShouldEqual, 1) post, err := rest.CreatePost(channel.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) cr, err = rest.FetchAccountActivityCount(account.Id, ses.ClientId) So(err, ShouldBeNil) So(cr, ShouldNotBeNil) So(cr.TotalCount, ShouldEqual, 2) }) }) }) }
func TestCollaborationDriveService(t *testing.T) { r := runner.New("collaboration-drive-tests") err := r.Init() if err != nil { panic(err) } defer r.Close() appConfig := config.MustRead(r.Conf.Path) modelhelper.Initialize(appConfig.Mongo) defer modelhelper.Close() // init with defaults mongoCache := cache.NewMongoCacheWithTTL(modelhelper.Mongo.Session) defer mongoCache.StopGC() handler := New(r.Log, mongoCache, appConfig, r.Kite) SkipConvey("while pinging collaboration", t, func() { // owner owner := apimodels.NewAccount() owner.OldId = AccountOldId.Hex() owner, err := rest.CreateAccount(owner) So(err, ShouldBeNil) So(owner, ShouldNotBeNil) groupName := apimodels.RandomGroupName() ownerSession, err := modelhelper.FetchOrCreateSession(owner.Nick, groupName) So(err, ShouldBeNil) So(ownerSession, ShouldNotBeNil) rand.Seed(time.Now().UnixNano()) req := &models.Ping{ AccountId: 1, FileId: fmt.Sprintf("%d", rand.Int63()), } Convey("while testing drive operations", func() { req := req req.CreatedAt = time.Now().UTC() Convey("should be able to create the file", func() { f, err := createTestFile(handler) if err != nil { t.Skip("Err happened, skipping: %s", err.Error()) } req.FileId = f.Id Convey("should be able to get the created file", func() { f2, err := handler.getFile(f.Id) if err != nil { t.Skip("Err happened, skipping: %s", err.Error()) } So(f2, ShouldNotBeNil) Convey("should be able to delete the created file", func() { err = handler.deleteFile(req.FileId) if err != nil { t.Skip("Err happened, skipping: %s", err.Error()) } Convey("should not be able to get the deleted file", func() { deadLine := time.After(TestTimeout) tick := time.Tick(time.Millisecond * 100) for { select { case <-tick: f2, err := handler.getFile(f.Id) if err != nil { t.Skip("Err happened, skipping: %s", err.Error()) } So(f2, ShouldBeNil) case <-deadLine: t.Skip("Could not get file after %s", TestTimeout) } } }) Convey("deleting the deleted file should not give error", func() { err = handler.deleteFile(req.FileId) if err != nil { t.Skip("Err happened, skipping: %s", err.Error()) } So(err, ShouldBeNil) }) }) }) }) }) }) }
func TestChannelHistory(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("While testing history of a channel", t, func() { Convey("We should be able to create it(channel) first", func() { groupName := models.RandomGroupName() account, err := models.CreateAccountInBothDbsWithNick("sinan") So(err, ShouldBeNil) So(account, ShouldNotBeNil) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) channel := models.CreateTypedGroupedChannelWithTest( account.Id, models.Channel_TYPE_GROUP, groupName, ) _, err = channel.AddParticipant(account.Id) So(err, ShouldBeNil) Convey("While posting a new message to it", func() { var channelParticipant *models.ChannelParticipant var err error Convey("We should be able to create a participant first", func() { channelParticipant, err = rest.CreateChannelParticipant(channel.Id, ses.ClientId) So(err, ShouldBeNil) So(channelParticipant, ShouldNotBeNil) Convey("Create posts with created participant", func() { channel := channel for i := 0; i < 10; i++ { post, err := rest.CreatePost(channel.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) So(post.Id, ShouldNotEqual, 0) So(post.Body, ShouldNotEqual, "") } Convey("We should be able to fetch the history", func() { history, err := rest.GetHistory( channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 10) }) Convey("We should be not able to fetch the history if the clientId is not set", func() { history, err := rest.GetHistory( channel.Id, &request.Query{ AccountId: account.Id, }, "", ) So(err, ShouldNotBeNil) So(history, ShouldBeNil) }) Convey("We should be not able to fetch the history if the clientId doesnt exist", func() { history, err := rest.GetHistory( channel.Id, &request.Query{ AccountId: account.Id, }, "foobarzaa", ) So(err, ShouldNotBeNil) So(history, ShouldBeNil) }) Convey("We should be able to get channel message count", func() { count, err := rest.CountHistory(channel.Id) So(err, ShouldBeNil) So(count, ShouldNotBeNil) So(count.TotalCount, ShouldEqual, 10) }) }) Convey("We should be able to check history according to request", func() { channel := channel for i := 0; i < 5; i++ { body := fmt.Sprintf("body%d", i) post, err := rest.CreatePostWithBodyAndAuth(channel.Id, body, ses.ClientId) // we need to wait while posting messages // if we dont use time sleep, Added_at field of the messages is // gonna be equal and this behavior is not expected situation // Then, tests will not be worked correctly time.Sleep(1000 * time.Millisecond) So(err, ShouldBeNil) So(post, ShouldNotBeNil) So(post.Id, ShouldNotEqual, 0) So(post.Body, ShouldNotEqual, "") } bodyMes := "postMid message" postMid, err := rest.CreatePostWithBodyAndAuth(channel.Id, bodyMes, ses.ClientId) So(postMid, ShouldNotBeNil) So(err, ShouldBeNil) for i := 5; i < 10; i++ { time.Sleep(1000 * time.Millisecond) body := fmt.Sprintf("body%d", i) post, err := rest.CreatePostWithBodyAndAuth(channel.Id, body, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) So(post.Id, ShouldNotEqual, 0) So(post.Body, ShouldNotEqual, "") } Convey("We should able to fetch the history with query request ", func() { history, err := rest.GetHistory( channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 11) }) Convey("We should able to fetch the history with query ADDED AT & ASC ", func() { history, err := rest.GetHistory( channel.Id, &request.Query{ From: postMid.CreatedAt, SortOrder: "ASC", }, ses.ClientId, ) var historyArr []string arr := []string{"postMid message", "body5", "body6", "body7", "body8", "body9"} for _, x := range history.MessageList { historyArr = append(historyArr, x.Message.Body) } So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 6) So(arr, ShouldResemble, historyArr) }) Convey("We should able to fetch the history with query ADDED AT & DESC ", func() { history, err := rest.GetHistory( channel.Id, &request.Query{ From: postMid.CreatedAt, SortOrder: "DESC", }, ses.ClientId, ) var historyArr []string arr := []string{"body4", "body3", "body2", "body1", "body0"} for _, x := range history.MessageList { historyArr = append(historyArr, x.Message.Body) } So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 5) So(arr, ShouldResemble, historyArr) }) Convey("We should able to fetch the with query ADDED AT & DESC ORDER& LIMIT ", func() { history, err := rest.GetHistory( channel.Id, &request.Query{ From: postMid.CreatedAt, SortOrder: "DESC", Limit: 3, }, ses.ClientId, ) var historyArr []string arr := []string{"body4", "body3", "body2"} for _, x := range history.MessageList { historyArr = append(historyArr, x.Message.Body) } So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 3) So(arr, ShouldResemble, historyArr) }) Convey("We should able to fetch the with query ADDED AT & ASC ORDER& LIMIT ", func() { history, err := rest.GetHistory( channel.Id, &request.Query{ From: postMid.CreatedAt, SortOrder: "ASC", Limit: 3, }, ses.ClientId, ) var historyArr []string arr := []string{"postMid message", "body5", "body6"} for _, x := range history.MessageList { historyArr = append(historyArr, x.Message.Body) } So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 3) So(arr, ShouldResemble, historyArr) }) }) }) }) }) }) }) }
func TestChannelCreation(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("while testing channel", t, func() { Convey("First Create Users", func() { account, err := models.CreateAccountInBothDbs() So(err, ShouldBeNil) groupName := models.RandomGroupName() ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) groupChannel := models.CreateTypedGroupedChannelWithTest( account.Id, models.Channel_TYPE_GROUP, groupName, ) So(err, ShouldBeNil) So(groupChannel, ShouldNotBeNil) nonOwnerAccount := models.NewAccount() nonOwnerAccount.OldId = AccountOldId2.Hex() nonOwnerAccount, err = rest.CreateAccount(nonOwnerAccount) So(err, ShouldBeNil) So(nonOwnerAccount, ShouldNotBeNil) noses, err := modelhelper.FetchOrCreateSession( nonOwnerAccount.Nick, groupName, ) So(err, ShouldBeNil) So(noses, ShouldNotBeNil) Convey("we should be able to create it", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_PRIVATE_MESSAGE, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) _, err = rest.AddChannelParticipant(channel1.Id, ses.ClientId, account.Id) So(err, ShouldBeNil) Convey("owner should be able to update it", func() { updatedPurpose := "another purpose from the paradise" channel1.Purpose = updatedPurpose channel2, err := rest.UpdateChannel(channel1, ses.ClientId) So(err, ShouldBeNil) So(channel2, ShouldNotBeNil) So(channel1.Purpose, ShouldEqual, channel1.Purpose) Convey("owner should be able to update payload", func() { if channel1.Payload == nil { channel1.Payload = gorm.Hstore{} } value := "value" channel1.Payload = gorm.Hstore{ "key": &value, } channel2, err := rest.UpdateChannel(channel1, ses.ClientId) So(err, ShouldBeNil) So(channel2, ShouldNotBeNil) So(channel1.Payload, ShouldNotBeNil) So(*channel1.Payload["key"], ShouldEqual, value) }) }) Convey("participant should be able to update only purpose, not name or payload", func() { _, err = rest.AddChannelParticipant(channel1.Id, ses.ClientId, nonOwnerAccount.Id) So(err, ShouldBeNil) updatedPurpose := "ChannelPurposeUpdated" updatedName := "ChannelNameUpdated" channel1.Name = updatedName channel1.Purpose = updatedPurpose channel2, err := rest.UpdateChannel(channel1, noses.ClientId) So(err, ShouldBeNil) So(channel2, ShouldNotBeNil) So(channel2.Name, ShouldNotBeNil) // participant cannot update channel name // can update only purpose of the channel So(channel2.Name, ShouldNotEqual, updatedName) So(channel2.Purpose, ShouldEqual, updatedPurpose) }) Convey("owner should be get channel by name", func() { channel2, err := rest.FetchChannelByName( account.Id, channel1.Name, channel1.GroupName, channel1.TypeConstant, ses.ClientId, ) So(err, ShouldBeNil) So(channel2, ShouldNotBeNil) So(channel1.Id, ShouldEqual, channel2.Id) So(channel1.Name, ShouldEqual, channel2.Name) So(channel1.GroupName, ShouldEqual, channel2.GroupName) So(channel1.GroupName, ShouldEqual, channel2.GroupName) }) Convey("unread count should be set", func() { channelContainer, err := rest.FetchChannelContainerByName(account.Id, channel1.Name, channel1.GroupName, channel1.TypeConstant, ses.ClientId) So(err, ShouldBeNil) So(channelContainer, ShouldNotBeNil) So(channelContainer.UnreadCount, ShouldEqual, 0) post, err := rest.CreatePost(channel1.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) channelContainer, err = rest.FetchChannelContainerByName(account.Id, channel1.Name, channel1.GroupName, channel1.TypeConstant, ses.ClientId) So(err, ShouldBeNil) So(channelContainer, ShouldNotBeNil) So(channelContainer.UnreadCount, ShouldEqual, 1) }) Convey("non-owner should not be able to update it", func() { updatedPurpose := "another purpose from the paradise" channel1.Purpose = updatedPurpose channel1.CreatorId = nonOwnerAccount.Id channel2, err := rest.UpdateChannel(channel1, noses.ClientId) So(err, ShouldNotBeNil) So(channel2, ShouldBeNil) }) Convey("non-owner should not be able to get channel by name", func() { _, err := rest.FetchChannelByName( nonOwnerAccount.Id, channel1.Name, channel1.GroupName, channel1.TypeConstant, noses.ClientId, ) So(err, ShouldNotBeNil) }) }) Convey("normal user shouldnt be able to add new participants to pinned activity channel", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_PINNED_ACTIVITY, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) channelParticipant, err := rest.AddChannelParticipant(channel1.Id, noses.ClientId, nonOwnerAccount.Id) // there should be an err So(err, ShouldNotBeNil) // channel should be nil So(channelParticipant, ShouldBeNil) }) Convey("owner should be able list participants", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_DEFAULT, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) // add first participant channelParticipant1, err := rest.AddChannelParticipant(channel1.Id, ses.ClientId, nonOwnerAccount.Id) // there should be an err So(err, ShouldBeNil) // channel should be nil So(channelParticipant1, ShouldNotBeNil) nonOwnerAccount2 := models.NewAccount() nonOwnerAccount2.OldId = AccountOldId3.Hex() nonOwnerAccount2, err = rest.CreateAccount(nonOwnerAccount2) So(err, ShouldBeNil) So(nonOwnerAccount2, ShouldNotBeNil) channelParticipant2, err := rest.AddChannelParticipant(channel1.Id, ses.ClientId, nonOwnerAccount2.Id) // there should be an err So(err, ShouldBeNil) // channel should be nil So(channelParticipant2, ShouldNotBeNil) participants, err := rest.ListChannelParticipants(channel1.Id, ses.ClientId) // there should be an err So(err, ShouldBeNil) So(participants, ShouldNotBeNil) // owner // nonOwner1 // nonOwner2 So(len(participants), ShouldEqual, 3) }) Convey("normal user should be able to list participants", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_DEFAULT, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) // add first participant channelParticipant1, err := rest.AddChannelParticipant(channel1.Id, ses.ClientId, nonOwnerAccount.Id) // there should be an err So(err, ShouldBeNil) // channel should be nil So(channelParticipant1, ShouldNotBeNil) nonOwnerAccount2 := models.NewAccount() nonOwnerAccount2.OldId = AccountOldId3.Hex() nonOwnerAccount2, err = rest.CreateAccount(nonOwnerAccount2) So(err, ShouldBeNil) So(nonOwnerAccount2, ShouldNotBeNil) nonOwnerSes2, err := modelhelper.FetchOrCreateSession(nonOwnerAccount2.Nick, groupName) So(err, ShouldBeNil) So(nonOwnerSes2, ShouldNotBeNil) channelParticipant2, err := rest.AddChannelParticipant(channel1.Id, ses.ClientId, nonOwnerAccount2.Id) // there should be an err So(err, ShouldBeNil) // channel should be nil So(channelParticipant2, ShouldNotBeNil) participants, err := rest.ListChannelParticipants(channel1.Id, nonOwnerSes2.ClientId) // there should be an err So(err, ShouldBeNil) So(participants, ShouldNotBeNil) // owner // nonOwner1 // nonOwner2 So(len(participants), ShouldEqual, 3) }) }) }) }) }
func TestChannelParticipantOperations(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("while testing channel participants", t, func() { Convey("First Create Users and initiate conversation", func() { ownerAccount, groupChannel, groupName := models.CreateRandomGroupDataWithChecks() ownerSes, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) So(ownerSes, ShouldNotBeNil) secondAccount, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(secondAccount, err) _, err = groupChannel.AddParticipant(secondAccount.Id) So(err, ShouldBeNil) thirdAccount, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(thirdAccount, err) _, err = groupChannel.AddParticipant(thirdAccount.Id) So(err, ShouldBeNil) forthAccount, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(forthAccount, err) _, err = groupChannel.AddParticipant(forthAccount.Id) So(err, ShouldBeNil) devrim, err := models.CreateAccountInBothDbsWithNick("devrim") tests.ResultedWithNoErrorCheck(devrim, err) _, err = groupChannel.AddParticipant(devrim.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) tests.ResultedWithNoErrorCheck(ses, err) secondSes, err := modelhelper.FetchOrCreateSession(secondAccount.Nick, groupName) tests.ResultedWithNoErrorCheck(secondSes, err) pmr := models.ChannelRequest{} pmr.AccountId = ownerAccount.Id pmr.Body = "new conversation" pmr.GroupName = groupName pmr.Recipients = []string{"devrim"} channelContainer, err := rest.SendPrivateChannelRequest(pmr, ownerSes.ClientId) So(err, ShouldBeNil) So(channelContainer, ShouldNotBeNil) Convey("First user should be able to add second and third users to conversation", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id, thirdAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) // it is four because first user is "devrim" here So(len(participants), ShouldEqual, 4) Convey("First user should not be able to re-add second participant", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 4) }) Convey("Second user should be able to leave conversation", func() { // token of account -> secondAccount _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, secondSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) Convey("A user who is not participant of a conversation should not be able to add another user to the conversation", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, secondSes.ClientId, forthAccount.Id) So(err, ShouldNotBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) }) Convey("Channel owner should be able to kick another conversation participant", func() { _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) Convey("when a user is blocked", func() { _, err = rest.BlockChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) Convey("it should not be in channel participant list", func() { participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) Convey("should not be able to add it back", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldNotBeNil) }) Convey("should be able to unblock", func() { _, err = rest.UnblockChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) Convey("it should not be in channel participant list still", func() { participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) Convey("when we add the same user as participant", func() { _, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id, thirdAccount.Id) So(err, ShouldBeNil) Convey("it should be in channel participant list", func() { participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 4) }) }) }) }) Convey("Second user should not be able to kick another conversation participant", func() { _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, secondSes.ClientId, thirdAccount.Id) So(err, ShouldNotBeNil) }) }) Convey("First user should be able to invite second user", func() { _, err = rest.InviteChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, secondAccount.Id) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) // it is four because first user is "devrim" here So(len(participants), ShouldEqual, 2) Convey("Second user should be able to reject invitation", func() { ses, err := modelhelper.FetchOrCreateSession(secondAccount.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) err = rest.RejectInvitation(channelContainer.Channel.Id, ses.ClientId) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 2) }) Convey("Second user should be able to accept invitation", func() { ses, err := modelhelper.FetchOrCreateSession(secondAccount.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) err = rest.AcceptInvitation(channelContainer.Channel.Id, ses.ClientId) So(err, ShouldBeNil) participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerSes.ClientId) So(err, ShouldBeNil) So(participants, ShouldNotBeNil) So(len(participants), ShouldEqual, 3) }) }) // TODO Until we find a better way for handling async stuff, this test is skipped. Instead of sleep, we should use some // timeouts for testing these kind of stuff. SkipConvey("All private messages must be deleted when all participant users leave the channel", func() { account := models.NewAccount() err = account.ByNick("devrim") So(err, ShouldBeNil) _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ses.ClientId, account.Id) So(err, ShouldBeNil) _, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ownerSes.ClientId, ownerAccount.Id) So(err, ShouldBeNil) time.Sleep(1 * time.Second) testChannel := models.NewChannel() err := testChannel.ById(channelContainer.Channel.Id) So(err, ShouldEqual, bongo.RecordNotFound) testChannelList := models.NewChannelMessageList() err = bongo.B.Unscoped().Where("channel_id = ?", channelContainer.Channel.Id).Find(testChannelList).Error So(err, ShouldEqual, bongo.RecordNotFound) testMessage := models.NewChannelMessage() err = bongo.B.Unscoped().Where("initial_channel_id = ?", channelContainer.Channel.Id).Find(testMessage).Error So(err, ShouldEqual, bongo.RecordNotFound) }) Convey("Users should not be able to add/remove users to/from bot channels", func() { ownerAccount, _, groupName := models.CreateRandomGroupDataWithChecks() participant := models.NewAccount() participant.OldId = AccountOldId.Hex() participant, err = rest.CreateAccount(participant) So(err, ShouldBeNil) So(participant, ShouldNotBeNil) ses, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) ch, err := rest.CreateChannelByGroupNameAndType(ownerAccount.Id, groupName, models.Channel_TYPE_BOT, ses.ClientId) So(err, ShouldBeNil) So(ch, ShouldNotBeNil) // account is -> ownerAccount.Id _, err = rest.AddChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(strings.Contains(err.Error(), "can not add participants for bot channel"), ShouldBeTrue) }) Convey("Users should be able to add/remove users to/from topic channels", func() { ownerAccount, _, groupName := models.CreateRandomGroupDataWithChecks() participant := models.NewAccount() participant.OldId = AccountOldId.Hex() participant, err = rest.CreateAccount(participant) So(err, ShouldBeNil) So(participant, ShouldNotBeNil) ses, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) ch, err := rest.CreateChannelByGroupNameAndType(ownerAccount.Id, groupName, models.Channel_TYPE_TOPIC, ses.ClientId) So(err, ShouldBeNil) So(ch, ShouldNotBeNil) // account is -> ownerAccount.Id _, err = rest.AddChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(err, ShouldBeNil) Convey("adding same user again should success", func() { _, err = rest.AddChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(err, ShouldBeNil) }) _, err = rest.DeleteChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(err, ShouldBeNil) Convey("removing same user again should success", func() { _, err = rest.DeleteChannelParticipant(ch.Id, ses.ClientId, participant.Id) So(err, ShouldBeNil) }) }) Convey("while removing users from group channels", func() { ownerAccount, _, groupName := models.CreateRandomGroupDataWithChecks() participant := models.NewAccount() participant.OldId = AccountOldId.Hex() participant, err = rest.CreateAccount(participant) So(err, ShouldBeNil) So(participant, ShouldNotBeNil) participant2 := models.NewAccount() participant2.OldId = AccountOldId.Hex() participant2, err = rest.CreateAccount(participant2) So(err, ShouldBeNil) So(participant2, ShouldNotBeNil) ownerSes, err := modelhelper.FetchOrCreateSession(ownerAccount.Nick, groupName) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(participant.Nick, groupName) So(err, ShouldBeNil) ch, err := rest.CreateChannelByGroupNameAndType(ownerAccount.Id, groupName, models.Channel_TYPE_GROUP, ownerSes.ClientId) So(err, ShouldBeNil) So(ch, ShouldNotBeNil) // ownerSes session is admin's session data _, err = rest.AddChannelParticipant(ch.Id, ownerSes.ClientId, participant.Id) So(err, ShouldBeNil) _, err = rest.AddChannelParticipant(ch.Id, ownerSes.ClientId, participant2.Id) So(err, ShouldBeNil) Convey("owner should be able to remove user from group channel", func() { // ownerSes session is admin's session data _, err = rest.DeleteChannelParticipant(ch.Id, ownerSes.ClientId, participant2.Id) So(err, ShouldBeNil) }) Convey("nonOwner should not be able to remove user from group channel", func() { // ses session is participant's session data _, err = rest.DeleteChannelParticipant(ch.Id, ses.ClientId, participant2.Id) So(err, ShouldNotBeNil) }) }) }) }) }) }
func TestPrivateMesssages(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("while testing private channels", t, func() { devrim, err := models.CreateAccountInBothDbsWithNick("devrim") So(err, ShouldBeNil) So(devrim, ShouldNotBeNil) sinan, err := models.CreateAccountInBothDbsWithNick("sinan") So(err, ShouldBeNil) So(sinan, ShouldNotBeNil) groupName := models.RandomGroupName() // cretae admin user account, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(account, err) models.CreateTypedGroupedChannelWithTest( account.Id, models.Channel_TYPE_GROUP, groupName, ) // fetch admin's session ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) groupChannel, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) tests.ResultedWithNoErrorCheck(groupChannel, err) recipient := models.NewAccount() recipient.OldId = AccountOldId2.Hex() recipient, err = rest.CreateAccount(recipient) So(err, ShouldBeNil) So(recipient, ShouldNotBeNil) recipient2 := models.NewAccount() recipient2.OldId = AccountOldId3.Hex() recipient2, err = rest.CreateAccount(recipient2) So(err, ShouldBeNil) So(recipient2, ShouldNotBeNil) Convey("participants should be a member of parent group", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body message for private message @devrim @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} _, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldNotBeNil) }) _, err = groupChannel.AddParticipant(sinan.Id) So(err, ShouldBeNil) _, err = groupChannel.AddParticipant(devrim.Id) So(err, ShouldBeNil) Convey("one can send private message to one person", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body message for private message @devrim @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) Convey("0 recipient should not fail", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message" pmr.GroupName = groupName pmr.Recipients = []string{} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) Convey("if sender is not defined but token is added, then shouldn't fail to create PM", func() { pmr := models.ChannelRequest{} pmr.AccountId = 0 pmr.Body = "this is a body for private message" pmr.GroupName = "" pmr.Recipients = []string{} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) Convey("one can send private message to multiple person", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"sinan"} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) Convey("private message response should have created channel", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message @devrim @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(cmc.Channel.TypeConstant, ShouldEqual, models.Channel_TYPE_PRIVATE_MESSAGE) So(cmc.Channel.Id, ShouldBeGreaterThan, 0) So(cmc.Channel.GroupName, ShouldEqual, groupName) So(cmc.Channel.PrivacyConstant, ShouldEqual, models.Channel_PRIVACY_PRIVATE) }) Convey("private message response should have participant status data", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message @devrim @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(cmc.IsParticipant, ShouldBeTrue) }) Convey("private message response should have participant count", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for @sinan private message @devrim" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(cmc.ParticipantCount, ShouldEqual, 3) }) Convey("private message response should have participant preview", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is @sinan a body for @devrim private message" pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(len(cmc.ParticipantsPreview), ShouldEqual, 3) }) Convey("private message response should have last Message", func() { body := "hi @devrim this is a body for private message also for @sinan" pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = body pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(cmc.LastMessage.Message.Body, ShouldEqual, body) }) Convey("private message should be listed by all recipients", func() { body := "hi @devrim this is a body for private message also for @sinan" pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = body pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) pm, err := rest.GetPrivateChannels(&request.Query{AccountId: account.Id, GroupName: groupName}, ses.ClientId) So(err, ShouldBeNil) So(pm, ShouldNotBeNil) So(len(pm), ShouldNotEqual, 0) So(pm[0], ShouldNotBeNil) So(pm[0].Channel.TypeConstant, ShouldEqual, models.Channel_TYPE_PRIVATE_MESSAGE) So(pm[0].Channel.Id, ShouldEqual, cmc.Channel.Id) So(pm[0].Channel.GroupName, ShouldEqual, cmc.Channel.GroupName) So(pm[0].LastMessage.Message.Body, ShouldEqual, cmc.LastMessage.Message.Body) So(pm[0].Channel.PrivacyConstant, ShouldEqual, models.Channel_PRIVACY_PRIVATE) So(len(pm[0].ParticipantsPreview), ShouldEqual, 3) So(pm[0].IsParticipant, ShouldBeTrue) }) Convey("user should be able to search private messages via purpose field", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "search private messages" pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} pmr.Purpose = "test me up" cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) query := request.Query{AccountId: account.Id, GroupName: groupName} _, err = rest.SearchPrivateChannels(&query, ses.ClientId) So(err, ShouldNotBeNil) query.Name = "test" pm, err := rest.SearchPrivateChannels(&query, ses.ClientId) So(err, ShouldBeNil) So(pm, ShouldNotBeNil) So(len(pm), ShouldNotEqual, 0) So(pm[0], ShouldNotBeNil) So(pm[0].Channel.TypeConstant, ShouldEqual, models.Channel_TYPE_PRIVATE_MESSAGE) So(pm[0].Channel.Id, ShouldEqual, cmc.Channel.Id) So(pm[0].Channel.GroupName, ShouldEqual, cmc.Channel.GroupName) So(pm[0].LastMessage.Message.Body, ShouldEqual, cmc.LastMessage.Message.Body) So(pm[0].Channel.PrivacyConstant, ShouldEqual, models.Channel_PRIVACY_PRIVATE) So(pm[0].IsParticipant, ShouldBeTrue) }) payload := gorm.Hstore{} bar := "bar" payload["foo"] = &bar Convey("given payload should be populated", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body message for private message @devrim @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} pmr.Payload = payload pcr, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(pcr, ShouldNotBeNil) So(pcr.Channel, ShouldNotBeNil) So(pcr.Channel.Payload, ShouldNotBeNil) So(len(pcr.Channel.Payload), ShouldBeGreaterThan, 0) So(*pcr.Channel.Payload["foo"], ShouldEqual, bar) }) Convey("user join activity should be listed by recipients", func() { groupName := models.RandomGroupName() // cretae admin user account, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(account, err) // fetch admin's session ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) groupChannel := models.CreateTypedGroupedChannelWithTest( account.Id, models.Channel_TYPE_GROUP, groupName, ) So(groupChannel, ShouldNotBeNil) _, err = groupChannel.AddParticipant(account.Id) So(err, ShouldBeNil) _, err = groupChannel.AddParticipant(devrim.Id) So(err, ShouldBeNil) _, err = groupChannel.AddParticipant(sinan.Id) So(err, ShouldBeNil) _, err = groupChannel.AddParticipant(recipient.Id) So(err, ShouldBeNil) pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "test private message participants" pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} if pmr.Payload == nil { pmr.Payload = gorm.Hstore{} } pic := "pictureSomethingLikeThat" pmr.Payload["link_embed"] = &pic cc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cc, ShouldNotBeNil) history, err := rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 2) // add participant _, err = rest.AddChannelParticipant(cc.Channel.Id, ses.ClientId, recipient.Id) So(err, ShouldBeNil) history, err = rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 3) So(history.MessageList[0].Message, ShouldNotBeNil) So(history.MessageList[0].Message.TypeConstant, ShouldEqual, models.ChannelMessage_TYPE_SYSTEM) So(history.MessageList[0].Message.Payload, ShouldNotBeNil) addedBy, ok := history.MessageList[0].Message.Payload["addedBy"] So(ok, ShouldBeTrue) So(*addedBy, ShouldEqual, account.Nick) systemType, ok := history.MessageList[0].Message.Payload["systemType"] So(ok, ShouldBeTrue) So(*systemType, ShouldEqual, models.ChannelRequestMessage_TYPE_JOIN) // we set link_embed into the payloadof the system message above. // But system message payload data will not have payload defined // by client side or else // As a result, system message will not be able to have link_embed payload data _, k := history.MessageList[0].Message.Payload["link_embed"] So(k, ShouldBeFalse) // try to add same participant _, err = rest.AddChannelParticipant(cc.Channel.Id, ses.ClientId, recipient.Id) So(err, ShouldBeNil) history, err = rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 3) }) Convey("user should not be able to edit join messages", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "test private message participants again" pmr.GroupName = groupName pmr.Recipients = []string{"devrim"} cc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cc, ShouldNotBeNil) _, err = rest.AddChannelParticipant(cc.Channel.Id, ses.ClientId, recipient.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) history, err := rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 3) joinMessage := history.MessageList[0].Message So(joinMessage, ShouldNotBeNil) _, err = rest.UpdatePost(joinMessage, ses.ClientId) So(err, ShouldNotBeNil) }) Convey("first chat message should include initial participants", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "test initial participation message" pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} cc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cc, ShouldNotBeNil) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) history, err := rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 2) joinMessage := history.MessageList[1].Message So(joinMessage.TypeConstant, ShouldEqual, models.ChannelMessage_TYPE_SYSTEM) So(joinMessage.Payload, ShouldNotBeNil) initialParticipants, ok := joinMessage.Payload["initialParticipants"] So(ok, ShouldBeTrue) systemType, ok := history.MessageList[1].Message.Payload["systemType"] So(ok, ShouldBeTrue) So(*systemType, ShouldEqual, models.ChannelRequestMessage_TYPE_INIT) participants := make([]string, 0) err = json.Unmarshal([]byte(*initialParticipants), &participants) So(err, ShouldBeNil) So(len(participants), ShouldEqual, 2) So(participants, ShouldContain, "devrim") // So(*addedBy, ShouldEqual, account.OldId) }) Convey("targetted account should be able to list private message channel of himself", nil) }) }) }
func TestChannelMessage(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("While testing channel messages given a channel", t, func() { account, groupChannel, groupName := models.CreateRandomGroupDataWithChecks() nonOwnerAccount := models.CreateAccountInBothDbsWithCheck() _, err := modelhelper.FetchOrCreateSession(nonOwnerAccount.Nick, groupName) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) Convey("message should be able added to the group channel", func() { post, err := rest.CreatePost(groupChannel.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) So(post.Id, ShouldNotEqual, 0) So(post.Body, ShouldNotEqual, "") Convey("message can be edited by owner", func() { initialPostBody := post.Body post.Body = "edited message" editedPost, err := rest.UpdatePost(post, ses.ClientId) So(err, ShouldBeNil) So(editedPost, ShouldNotBeNil) // body should not be same So(initialPostBody, ShouldNotEqual, editedPost.Body) }) // for now social worker handles this issue Convey("message can be edited by an admin", nil) Convey("message can not be edited by non-owner", nil) }) Convey("topic messages initialChannelId must be set as owner group channel id", func() { ses, err = modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) topicChannel, err := rest.CreateChannelByGroupNameAndType(account.Id, "koding", models.Channel_TYPE_TOPIC, ses.ClientId) So(err, ShouldBeNil) So(topicChannel, ShouldNotBeNil) post, err := rest.CreatePost(topicChannel.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) So(post.InitialChannelId, ShouldNotEqual, topicChannel.Id) publicChannel, err := rest.GetChannelWithToken(post.InitialChannelId, ses.ClientId) So(err, ShouldBeNil) So(publicChannel.TypeConstant, ShouldEqual, models.Channel_TYPE_GROUP) }) Convey("message can be deleted by owner", func() { post, err := rest.CreatePost(groupChannel.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) err = rest.DeletePost(post.Id, ses.ClientId) So(err, ShouldBeNil) post2, err := rest.GetPost(post.Id, ses.ClientId) So(err, ShouldNotBeNil) So(post2, ShouldBeNil) }) Convey("message should not have payload, if user does not allow", func() { h := http.Header{} h.Add("X-Forwarded-For", "208.72.139.54") post, err := rest.CreatePostWithHeader(groupChannel.Id, h, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) So(post.Payload, ShouldBeNil) }) Convey("Message should have location if user allowed", func() { payload := make(map[string]interface{}) payload["saveLocation"] = "Manisa" post, err := rest.CreatePostWithPayload(groupChannel.Id, payload, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) So(post.Payload, ShouldNotBeNil) So(*(post.Payload["saveLocation"]), ShouldEqual, "Manisa") }) // handled by social worker Convey("message can be deleted by an admin", nil) Convey("message can not be edited by non-owner", nil) Convey("we should be able to get replies with \"from\" query param", nil) Convey("while deleting messages, they should be removed from all channels", nil) Convey("message can contain payload", func() { payload := make(map[string]interface{}) payload["key1"] = "value1" payload["key2"] = 2 payload["key3"] = true payload["key4"] = 3.4 post, err := rest.CreatePostWithPayload(groupChannel.Id, payload, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) So(post.Payload, ShouldNotBeNil) So(*(post.Payload["key1"]), ShouldEqual, "value1") So(*(post.Payload["key2"]), ShouldEqual, "2") So(*(post.Payload["key3"]), ShouldEqual, "true") So(*(post.Payload["key4"]), ShouldEqual, "3.4") }) }) }) }
func TestFollowedTopics(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("While testing followed topics", t, func() { Convey("First Create User", func() { account, _, groupName := models.CreateRandomGroupDataWithChecks() ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) nonOwnerAccount := models.NewAccount() nonOwnerAccount.OldId = AccountOldId.Hex() nonOwnerAccount, err = rest.CreateAccount(nonOwnerAccount) So(err, ShouldBeNil) So(nonOwnerAccount, ShouldNotBeNil) topicChannel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_TOPIC, ses.ClientId, ) So(err, ShouldBeNil) topicChannel2, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_TOPIC, ses.ClientId, ) So(err, ShouldBeNil) Convey("user should be able to follow one topic", func() { channelParticipant, err := rest.AddChannelParticipant(topicChannel1.Id, ses.ClientId, account.Id) // there should be an err So(err, ShouldBeNil) // channel should be nil So(channelParticipant, ShouldNotBeNil) followedChannels, err := rest.FetchFollowedChannels(account.Id, ses.ClientId) So(err, ShouldBeNil) So(followedChannels, ShouldNotBeNil) So(len(followedChannels), ShouldBeGreaterThanOrEqualTo, 1) }) Convey("user should be able to follow two topic", func() { channelParticipant, err := rest.AddChannelParticipant(topicChannel1.Id, ses.ClientId, account.Id) So(err, ShouldBeNil) So(channelParticipant, ShouldNotBeNil) channelParticipant, err = rest.AddChannelParticipant(topicChannel2.Id, ses.ClientId, account.Id) So(err, ShouldBeNil) So(channelParticipant, ShouldNotBeNil) followedChannels, err := rest.FetchFollowedChannels(account.Id, ses.ClientId) So(err, ShouldBeNil) So(followedChannels, ShouldNotBeNil) So(len(followedChannels), ShouldBeGreaterThanOrEqualTo, 2) }) Convey("user should be participant of the followed topic", func() { channelParticipant, err := rest.AddChannelParticipant(topicChannel1.Id, ses.ClientId, account.Id) // there should be an err So(err, ShouldBeNil) // channel should be nil So(channelParticipant, ShouldNotBeNil) followedChannels, err := rest.FetchFollowedChannels(account.Id, ses.ClientId) So(err, ShouldBeNil) So(followedChannels, ShouldNotBeNil) So(len(followedChannels), ShouldBeGreaterThanOrEqualTo, 1) So(followedChannels[0].IsParticipant, ShouldBeTrue) }) Convey("user should not be a participant of the un-followed topic", func() { channelParticipant, err := rest.AddChannelParticipant(topicChannel1.Id, ses.ClientId, account.Id) So(err, ShouldBeNil) So(channelParticipant, ShouldNotBeNil) followedChannels, err := rest.FetchFollowedChannels(account.Id, ses.ClientId) So(err, ShouldBeNil) So(followedChannels, ShouldNotBeNil) currentParticipatedChannelCount := len(followedChannels) channelParticipant, err = rest.DeleteChannelParticipant(topicChannel1.Id, ses.ClientId, account.Id) So(err, ShouldBeNil) So(channelParticipant, ShouldNotBeNil) followedChannels, err = rest.FetchFollowedChannels(account.Id, ses.ClientId) So(err, ShouldBeNil) So(followedChannels, ShouldNotBeNil) lastParticipatedChannelCount := len(followedChannels) So(currentParticipatedChannelCount-lastParticipatedChannelCount, ShouldEqual, 1) }) Convey("participant count of the followed topic should be greater than 0", func() { channelParticipant, err := rest.AddChannelParticipant(topicChannel1.Id, ses.ClientId, account.Id) // there should be an err So(err, ShouldBeNil) // channel should be nil So(channelParticipant, ShouldNotBeNil) followedChannels, err := rest.FetchFollowedChannels(account.Id, ses.ClientId) So(err, ShouldBeNil) So(followedChannels, ShouldNotBeNil) So(len(followedChannels), ShouldBeGreaterThanOrEqualTo, 1) So(followedChannels[0].ParticipantCount, ShouldBeGreaterThanOrEqualTo, 1) }) }) }) }) }
func TestPresenceDailyFetchActiveAccounts(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("With given presence data", t, func() { acc1, _, groupName := CreateRandomGroupDataWithChecks() gr, err := modelhelper.GetGroup(groupName) tests.ResultedWithNoErrorCheck(gr, err) err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc1.OldId), gr.Id) So(err, ShouldBeNil) p1 := &PresenceDaily{ AccountId: acc1.Id, GroupName: groupName, CreatedAt: time.Now().UTC(), } So(p1.Create(), ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(acc1.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) for i := 0; i < 5; i++ { // create accounts acc2 := CreateAccountInBothDbsWithCheck() // add them to presence p1 := &PresenceDaily{ AccountId: acc2.Id, GroupName: groupName, CreatedAt: time.Now().UTC(), } So(p1.Create(), ShouldBeNil) } Convey("FetchActiveAccounts should not work properly if query is nil", func() { query := request.NewQuery() c1, err := (&PresenceDaily{}).FetchActiveAccounts(query) So(err, ShouldNotBeNil) So(c1, ShouldBeNil) Convey("FetchActiveAccounts should work properly", func() { query := request.NewQuery().SetDefaults() query.GroupName = groupName c1, err := (&PresenceDaily{}).FetchActiveAccounts(query) So(err, ShouldBeNil) So(c1, ShouldNotBeNil) }) Convey("Pagination skip should work properly", func() { query := request.NewQuery().SetDefaults() query.GroupName = groupName query.Skip = 20 c1, err := (&PresenceDaily{}).FetchActiveAccounts(query) So(err, ShouldNotBeNil) So(err, ShouldEqual, bongo.RecordNotFound) So(c1, ShouldBeNil) Convey("Pagination limit should work properly", func() { query := request.NewQuery().SetDefaults() query.GroupName = groupName query.Limit = 4 c1, err := (&PresenceDaily{}).FetchActiveAccounts(query) So(err, ShouldBeNil) So(c1, ShouldNotBeNil) So(len(c1.Accounts), ShouldEqual, 4) }) }) }) }) }) }
func TestGroupChannel(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("while testing pinned activity channel", t, func() { groupName := models.RandomGroupName() account, err := models.CreateAccountInBothDbs() So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) models.CreateTypedGroupedChannelWithTest( account.Id, models.Channel_TYPE_GROUP, groupName, ) Convey("channel should be there", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) channel2, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) So(channel2, ShouldNotBeNil) }) Convey("group channel should be shown before announcement", func() { account, err := models.CreateAccountInBothDbs() So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) _, err = rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) _, err = rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_ANNOUNCEMENT, ses.ClientId, ) So(err, ShouldBeNil) channels, err := rest.FetchChannelsByQuery(account.Id, &request.Query{ GroupName: groupName, Type: models.Channel_TYPE_GROUP, }, ses.ClientId, ) So(err, ShouldBeNil) So(len(channels), ShouldEqual, 2) So(channels[0].TypeConstant, ShouldEqual, models.Channel_TYPE_GROUP) So(channels[1].TypeConstant, ShouldEqual, models.Channel_TYPE_ANNOUNCEMENT) }) Convey("owner should be able to update it", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) // fetching channel returns creator id _, err = rest.UpdateChannel(channel1, ses.ClientId) So(err, ShouldBeNil) }) Convey("owner should only be able to update name and purpose of the channel", nil) Convey("normal user should be able to update it if and only if user is creator or participant", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) anotherAccount := models.NewAccount() anotherAccount.OldId = bson.NewObjectId().Hex() anotherAccount, err = rest.CreateAccount(anotherAccount) So(err, ShouldBeNil) So(account, ShouldNotBeNil) ses, err := modelhelper.FetchOrCreateSession(anotherAccount.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) _, err = rest.UpdateChannel(channel1, ses.ClientId) So(err, ShouldBeNil) }) Convey("owner cant delete it", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) err = rest.DeleteChannel(account.Id, channel1.Id) So(err, ShouldNotBeNil) }) Convey("normal user cant delete it", func() { channel1, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) So(channel1, ShouldNotBeNil) err = rest.DeleteChannel(rand.Int63(), channel1.Id) So(err, ShouldNotBeNil) }) Convey("member can post status update", nil) Convey("non-member can not post status update", nil) }) }) }
func TestChannelByParticipants(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("while fetching channels by their participants", t, func() { admin1, _, groupName1 := models.CreateRandomGroupDataWithChecks() ses1, err := modelhelper.FetchOrCreateSession(admin1.Nick, groupName1) So(err, ShouldBeNil) So(ses1, ShouldNotBeNil) acc1, err := models.CreateAccountInBothDbs() So(err, ShouldBeNil) So(acc1, ShouldNotBeNil) acc2, err := models.CreateAccountInBothDbs() So(err, ShouldBeNil) So(acc1, ShouldNotBeNil) tc1 := createChannelAndParticipants(admin1, groupName1, models.Channel_TYPE_TOPIC, ses1.ClientId, acc1.Id, acc2.Id) tc2 := createChannelAndParticipants(admin1, groupName1, models.Channel_TYPE_TOPIC, ses1.ClientId, acc1.Id, acc2.Id) Convey("valid request should return valid response", func() { channels, err := rest.FetchChannelsByParticipants([]int64{acc1.Id, acc2.Id}, models.Channel_TYPE_TOPIC, ses1.ClientId) // there should be an err So(err, ShouldBeNil) So(channels, ShouldNotBeNil) So(len(channels), ShouldEqual, 2) So(tc1.Id, ShouldEqual, channels[0].Channel.Id) So(tc2.Id, ShouldEqual, channels[1].Channel.Id) }) Convey("other group's content should not be in the result set", func() { groupName2 := models.RandomGroupName() models.CreateTypedGroupedChannelWithTest( admin1.Id, models.Channel_TYPE_GROUP, groupName2, ) ses2, err := modelhelper.FetchOrCreateSession(admin1.Nick, groupName2) So(err, ShouldBeNil) So(ses2, ShouldNotBeNil) gtc1 := createChannelAndParticipants(admin1, groupName2, models.Channel_TYPE_TOPIC, ses2.ClientId, acc1.Id, acc2.Id) gtc2 := createChannelAndParticipants(admin1, groupName2, models.Channel_TYPE_TOPIC, ses2.ClientId, acc1.Id, acc2.Id) channels, err := rest.FetchChannelsByParticipants([]int64{acc1.Id, acc2.Id}, models.Channel_TYPE_TOPIC, ses1.ClientId) // there should be an err So(err, ShouldBeNil) So(channels, ShouldNotBeNil) So(len(channels), ShouldEqual, 2) So(channels[0].Channel.GroupName, ShouldEqual, groupName1) So(channels[1].Channel.GroupName, ShouldEqual, groupName1) So(tc1.Id, ShouldEqual, channels[0].Channel.Id) So(tc2.Id, ShouldEqual, channels[1].Channel.Id) channels, err = rest.FetchChannelsByParticipants([]int64{acc1.Id, acc2.Id}, models.Channel_TYPE_TOPIC, ses2.ClientId) // there should be an err So(err, ShouldBeNil) So(channels, ShouldNotBeNil) So(len(channels), ShouldEqual, 2) So(channels[0].Channel.GroupName, ShouldEqual, groupName2) So(channels[1].Channel.GroupName, ShouldEqual, groupName2) So(gtc1.Id, ShouldEqual, channels[0].Channel.Id) So(gtc2.Id, ShouldEqual, channels[1].Channel.Id) }) }) }) }
func TestPinnedActivityChannel(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { SkipConvey("while testing pinned activity channel", t, func() { groupName := models.RandomGroupName() account := models.NewAccount() account.OldId = AccountOldId.Hex() account, err := rest.CreateAccount(account) So(err, ShouldBeNil) So(account, ShouldNotBeNil) So(account.Id, ShouldNotEqual, 0) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) nonOwnerAccount := models.NewAccount() nonOwnerAccount.OldId = AccountOldId.Hex() nonOwnerAccount, err = rest.CreateAccount(nonOwnerAccount) So(err, ShouldBeNil) So(nonOwnerAccount, ShouldNotBeNil) nonOwnerSes, err := modelhelper.FetchOrCreateSession(nonOwnerAccount.Nick, groupName) So(err, ShouldBeNil) So(nonOwnerSes, ShouldNotBeNil) groupChannel, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_GROUP, ses.ClientId, ) So(err, ShouldBeNil) So(groupChannel, ShouldNotBeNil) post, err := rest.CreatePost(groupChannel.Id, ses.ClientId) So(err, ShouldBeNil) So(post, ShouldNotBeNil) Convey("requester should have one", func() { account := account channel, err := rest.FetchPinnedActivityChannel(account.Id, groupName) So(err, ShouldBeNil) So(channel, ShouldNotBeNil) So(channel.Id, ShouldNotEqual, 0) So(channel.TypeConstant, ShouldEqual, models.Channel_TYPE_PINNED_ACTIVITY) So(channel.CreatorId, ShouldEqual, account.Id) }) Convey("owner should be able to update it", nil) Convey("non-owner should not be able to update it", nil) Convey("owner should not be able to add new participants into it", func() { channel, err := rest.FetchPinnedActivityChannel(account.Id, groupName) So(err, ShouldBeNil) So(channel, ShouldNotBeNil) channelParticipant, err := rest.AddChannelParticipant(channel.Id, ses.ClientId, nonOwnerAccount.Id) // there should be an err So(err, ShouldNotBeNil) // channel should be nil So(channelParticipant, ShouldBeNil) }) Convey("normal user shouldnt be able to add new participants to it", func() { channel, err := rest.FetchPinnedActivityChannel(account.Id, groupName) So(err, ShouldBeNil) So(channel, ShouldNotBeNil) channelParticipant, err := rest.AddChannelParticipant(channel.Id, nonOwnerSes.ClientId, nonOwnerAccount.Id) // there should be an err So(err, ShouldNotBeNil) // channel should be nil So(channelParticipant, ShouldBeNil) }) Convey("owner should not be able to remove participant from it", func() { channel, err := rest.FetchPinnedActivityChannel(account.Id, groupName) So(err, ShouldBeNil) So(channel, ShouldNotBeNil) channelParticipant, err := rest.DeleteChannelParticipant(channel.Id, ses.ClientId, nonOwnerAccount.Id) // there should be an err So(err, ShouldNotBeNil) // channel should be nil So(channelParticipant, ShouldBeNil) }) Convey("normal user shouldnt be able to remove participants from it", func() { channel, err := rest.FetchPinnedActivityChannel(account.Id, groupName) So(err, ShouldBeNil) So(channel, ShouldNotBeNil) channelParticipant, err := rest.DeleteChannelParticipant(channel.Id, nonOwnerSes.ClientId, nonOwnerAccount.Id) // there should be an err So(err, ShouldNotBeNil) // channel should be nil So(channelParticipant, ShouldBeNil) }) Convey("owner should be able to add new message into it", func() { _, err := rest.AddPinnedMessage(account.Id, post.Id, "koding") // there should be an err So(err, ShouldBeNil) _, err = rest.RemovePinnedMessage(account.Id, post.Id, "koding") So(err, ShouldBeNil) }) Convey("owner should be able to list messages", func() { groupName := "testgroup" + strconv.FormatInt(rand.Int63(), 10) pinnedChannel, err := rest.FetchPinnedActivityChannel(account.Id, groupName) So(err, ShouldBeNil) So(pinnedChannel, ShouldNotBeNil) groupChannel, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_DEFAULT, ses.ClientId, ) So(err, ShouldBeNil) So(groupChannel, ShouldNotBeNil) post1, err := rest.CreatePostWithBody(groupChannel.Id, nonOwnerAccount.Id, "create a message #1times") So(err, ShouldBeNil) So(post1, ShouldNotBeNil) _, err = rest.AddPinnedMessage(nonOwnerAccount.Id, post1.Id, groupName) // there should be an err So(err, ShouldBeNil) post2, err := rest.CreatePostWithBody(groupChannel.Id, nonOwnerAccount.Id, "create a message #1another") So(err, ShouldBeNil) So(post2, ShouldNotBeNil) _, err = rest.AddPinnedMessage(nonOwnerAccount.Id, post2.Id, groupName) // there should be an err So(err, ShouldBeNil) //time.Sleep(time.Second * 5) history, err := rest.FetchPinnedMessages(account.Id, groupName) // there should be an err So(err, ShouldBeNil) // channel should be nil So(history, ShouldNotBeNil) // message count should be 2 So(len(history.MessageList), ShouldEqual, 2) // unread count should be 0 So(history.UnreadCount, ShouldEqual, 0) // old id should be the same one So(history.MessageList[0].AccountOldId, ShouldContainSubstring, nonOwnerAccount.OldId) // replies count should be 0 So(len(history.MessageList[0].Replies), ShouldEqual, 0) }) Convey("Messages shouldnt be added as pinned twice ", func() { // use account id as message id _, err := rest.AddPinnedMessage(account.Id, post.Id, "koding") // there should be an err So(err, ShouldBeNil) // use account id as message id, pin message is idempotent, if it is // in the channel, wont give error _, err = rest.AddPinnedMessage(account.Id, post.Id, "koding") // there should not be an err So(err, ShouldBeNil) }) Convey("Non-exist message should not be added as pinned ", nil) }) }) }
func TestCollaboration(t *testing.T) { r := runner.New("collaboration-tests") err := r.Init() if err != nil { panic(err) } defer r.Close() appConfig := config.MustRead(r.Conf.Path) modelhelper.Initialize(appConfig.Mongo) defer modelhelper.Close() // init with defaults mongoCache := cache.NewMongoCacheWithTTL(modelhelper.Mongo.Session) defer mongoCache.StopGC() handler := New(r.Log, mongoCache, appConfig, r.Kite) Convey("while pinging collaboration", t, func() { // owner owner := apimodels.NewAccount() owner.OldId = AccountOldId.Hex() owner, err := rest.CreateAccount(owner) So(err, ShouldBeNil) So(owner, ShouldNotBeNil) groupName := apimodels.RandomGroupName() ownerSession, err := modelhelper.FetchOrCreateSession(owner.Nick, groupName) So(err, ShouldBeNil) So(ownerSession, ShouldNotBeNil) rand.Seed(time.Now().UnixNano()) req := &models.Ping{ AccountId: 1, FileId: fmt.Sprintf("%d", rand.Int63()), } Convey("while testing Ping", func() { Convey("reponse should be success with valid ping", func() { err = handler.Ping(req) So(err, ShouldBeNil) }) Convey("reponse should be success with invalid FileId", func() { req.FileId = "" err = handler.Ping(req) So(err, ShouldBeNil) }) Convey("reponse should be success with invalid AccountId", func() { req.AccountId = 0 err = handler.Ping(req) So(err, ShouldBeNil) }) Convey("reponse should be success with invalid session", func() { req := req // prepare an invalid session here req.CreatedAt = time.Now().UTC() err = mongoCache.SetEx(PrepareFileKey(req.FileId), ExpireSessionKeyDuration, req.CreatedAt.Add(-terminateSessionDuration)) err = handler.Ping(req) So(err, ShouldBeNil) }) Convey("after sleep time", func() { req := req Convey("expired session should get invalidSessoin", func() { st := sleepTime sleepTime = time.Millisecond * 110 tsd := terminateSessionDuration terminateSessionDuration = 100 // set durations back to the original value defer func() { sleepTime = st terminateSessionDuration = tsd }() req.CreatedAt = time.Now().UTC() // prepare a valid key err = mongoCache.SetEx( PrepareFileKey(req.FileId), terminateSessionDuration, // expire the key after this period req.CreatedAt.Unix()) // while sleeping here, redis key should be removed // and we can understand that the Collab session is expired time.Sleep(sleepTime) req := req err = handler.wait(req) So(err, ShouldEqual, errSessionInvalid) }) Convey("deadlined session should get errDeadlineReached", func() { st := sleepTime sleepTime = time.Millisecond * 110 dd := deadLineDuration deadLineDuration = 100 // set durations back to the original value defer func() { sleepTime = st deadLineDuration = dd }() req := req err := handler.wait(req) So(err, ShouldEqual, errDeadlineReached) }) }) }) Convey("while testing checkIfKeyIsValid", func() { req := req req.CreatedAt = time.Now().UTC() // prepare a valid key err := mongoCache.SetEx( PrepareFileKey(req.FileId), ExpireSessionKeyDuration, // expire the key after this period req.CreatedAt.Unix(), // value - unix time ) So(err, ShouldBeNil) Convey("valid key should return nil", func() { err = handler.checkIfKeyIsValid(req) So(err, ShouldBeNil) }) Convey("invalid key should return errSessionInvalid", func() { req := req // override fileId req.FileId = fmt.Sprintf("%d", rand.Int63()) err = handler.checkIfKeyIsValid(req) So(err, ShouldEqual, errSessionInvalid) }) Convey("invalid (non-timestamp) value should return errSessionInvalid", func() { req := req req.CreatedAt = time.Now().UTC() err = mongoCache.SetEx( PrepareFileKey(req.FileId), ExpireSessionKeyDuration, // expire the key after this period "req.CreatedAt.Unix()", // replace timestamp with unix time ) err = handler.checkIfKeyIsValid(req) So(err, ShouldEqual, errSessionInvalid) }) Convey("old ping time should return errSessionInvalid", func() { req := req req.CreatedAt = time.Now().UTC() err = mongoCache.SetEx( PrepareFileKey(req.FileId), ExpireSessionKeyDuration, // expire the key after this period req.CreatedAt.Add(-terminateSessionDuration).Unix(), ) err = handler.checkIfKeyIsValid(req) So(err, ShouldEqual, errSessionInvalid) }) Convey("previous ping time is in safe area", func() { req := req testPingTimes(req, -1, mongoCache, handler, nil) }) Convey("0 ping time is in safe area", func() { req := req testPingTimes(req, 0, mongoCache, handler, nil) }) Convey("2 ping time is in safe area", func() { req := req testPingTimes(req, 2, mongoCache, handler, nil) }) Convey("3 ping time is in safe area", func() { req := req testPingTimes(req, 3, mongoCache, handler, nil) }) Convey("4 ping time is not in safe area - because we already reverted the time ", func() { req := req testPingTimes(req, 4, mongoCache, handler, errSessionInvalid) }) Convey("5 ping time is not in safe area ", func() { req := req testPingTimes(req, 5, mongoCache, handler, errSessionInvalid) }) }) }) }
func TestAddRemoveChannelParticipant(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { controller := &Controller{} Convey("While testing add/remove channel participants", t, func() { account := models.CreateAccountInBothDbsWithCheck() groupName := models.RandomGroupName() _ = models.CreateTypedGroupedChannelWithTest( account.Id, models.Channel_TYPE_GROUP, groupName, ) // fetch admin's session ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) pe := &models.ParticipantEvent{} Convey("When user follows/unfollows a topic, they must be notified", func() { topicChannel, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_TOPIC, ses.ClientId, ) tests.ResultedWithNoErrorCheck(topicChannel, err) pe.Id = topicChannel.Id cp := &models.ChannelParticipant{} cp.AccountId = account.Id pe.Participants = []*models.ChannelParticipant{cp} participants, err := controller.fetchNotifiedParticipantIds(topicChannel, pe, AddedToChannelEventName) So(err, ShouldBeNil) So(len(participants), ShouldEqual, 1) So(participants[0], ShouldEqual, account.Id) participants, err = controller.fetchNotifiedParticipantIds(topicChannel, pe, RemovedFromChannelEventName) So(err, ShouldBeNil) So(len(participants), ShouldEqual, 1) So(participants[0], ShouldEqual, account.Id) }) Convey("When user joins a topic, only participant user must be notified", func() { privateChannel, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_PRIVATE_MESSAGE, ses.ClientId, ) tests.ResultedWithNoErrorCheck(privateChannel, err) pe.Id = privateChannel.Id cp := &models.ChannelParticipant{} cp.AccountId = account.Id pe.Participants = []*models.ChannelParticipant{cp} participants, err := controller.fetchNotifiedParticipantIds(privateChannel, pe, AddedToChannelEventName) So(err, ShouldBeNil) So(len(participants), ShouldEqual, 1) So(participants[0], ShouldEqual, account.Id) }) Convey("When user leaves a topic, all participants musts be notified", func() { privateChannel, err := rest.CreateChannelByGroupNameAndType( account.Id, groupName, models.Channel_TYPE_PRIVATE_MESSAGE, ses.ClientId, ) tests.ResultedWithNoErrorCheck(privateChannel, err) pe.Id = privateChannel.Id cp := &models.ChannelParticipant{} cp.AccountId = account.Id pe.Participants = []*models.ChannelParticipant{cp} participants, err := controller.fetchNotifiedParticipantIds(privateChannel, pe, RemovedFromChannelEventName) tests.ResultedWithNoErrorCheck(participants, err) So(len(participants), ShouldEqual, 2) So(participants[0], ShouldEqual, account.Id) }) }) }) }
// New gives new, registered kloud kite. // // If conf contains invalid or missing configuration, it return non-nil error. func New(conf *Config) (*Kloud, error) { k := kite.New(stack.NAME, stack.VERSION) k.Config = kiteconfig.MustGet() k.Config.Port = conf.Port k.ClientFunc = httputil.ClientFunc(conf.DebugMode) if conf.DebugMode { k.SetLogLevel(kite.DEBUG) } if conf.Region != "" { k.Config.Region = conf.Region } if conf.Environment != "" { k.Config.Environment = conf.Environment } // TODO(rjeczalik): refactor modelhelper methods to not use global DB modelhelper.Initialize(conf.MongoURL) sess, err := newSession(conf, k) if err != nil { return nil, err } e := newEndpoints(conf) sess.Log.Debug("Konfig.Endpoints: %s", util.LazyJSON(e)) authUsers := map[string]string{ "kloudctl": conf.KloudSecretKey, } restClient := httputil.DefaultRestClient(conf.DebugMode) storeOpts := &credential.Options{ MongoDB: sess.DB, Log: sess.Log.New("stackcred"), Client: restClient, } if !conf.NoSneaker { storeOpts.CredURL = e.Social().WithPath("/credential").Private.URL } sess.Log.Debug("storeOpts: %+v", storeOpts) userPrivateKey, userPublicKey := userMachinesKeys(conf.UserPublicKey, conf.UserPrivateKey) stacker := &provider.Stacker{ DB: sess.DB, Log: sess.Log, Kite: sess.Kite, Userdata: sess.Userdata, Debug: conf.DebugMode, KloudSecretKey: conf.KloudSecretKey, CredStore: credential.NewStore(storeOpts), TunnelURL: conf.TunnelURL, SSHKey: &publickeys.Keys{ KeyName: publickeys.DeployKeyName, PrivateKey: userPrivateKey, PublicKey: userPublicKey, }, } stats := common.MustInitMetrics(Name) kloud := &Kloud{ Kite: k, Stack: stack.New(), Queue: &queue.Queue{ Interval: 5 * time.Second, Log: sess.Log.New("queue"), Kite: k, MongoDB: sess.DB, }, } authFn := func(opts *api.AuthOptions) (*api.Session, error) { s, err := modelhelper.FetchOrCreateSession(opts.User.Username, opts.User.Team) if err != nil { return nil, err } return &api.Session{ ClientID: s.ClientId, User: &api.User{ Username: s.Username, Team: s.GroupName, }, }, nil } transport := &api.Transport{ RoundTripper: storeOpts.Client.Transport, AuthFunc: api.NewCache(authFn).Auth, Debug: conf.DebugMode, } if conf.DebugMode { transport.Log = sess.Log } kloud.Stack.Endpoints = e kloud.Stack.Userdata = sess.Userdata kloud.Stack.DescribeFunc = provider.Desc kloud.Stack.CredClient = credential.NewClient(storeOpts) kloud.Stack.MachineClient = machine.NewClient(machine.NewMongoDatabase()) kloud.Stack.TeamClient = team.NewClient(team.NewMongoDatabase()) kloud.Stack.PresenceClient = client.NewInternal(e.Social().Private.String()) kloud.Stack.PresenceClient.HTTPClient = restClient kloud.Stack.RemoteClient = &remoteapi.Client{ Client: storeOpts.Client, Transport: transport, Endpoint: e.Koding.Private.URL, } kloud.Stack.ContextCreator = func(ctx context.Context) context.Context { return session.NewContext(ctx, sess) } kloud.Stack.Metrics = stats // RSA key pair that we add to the newly created machine for // provisioning. kloud.Stack.PublicKeys = stacker.SSHKey kloud.Stack.DomainStorage = sess.DNSStorage kloud.Stack.Domainer = sess.DNSClient kloud.Stack.Locker = stacker kloud.Stack.Log = sess.Log kloud.Stack.SecretKey = conf.KloudSecretKey for _, p := range provider.All() { s := stacker.New(p) if err = kloud.Stack.AddProvider(p.Name, s); err != nil { return nil, err } kloud.Queue.Register(s) sess.Log.Debug("registering %q provider", p.Name) } go kloud.Queue.Run() if conf.KeygenAccessKey != "" && conf.KeygenSecretKey != "" { cfg := &keygen.Config{ AccessKey: conf.KeygenAccessKey, SecretKey: conf.KeygenSecretKey, Region: conf.KeygenRegion, Bucket: conf.KeygenBucket, AuthExpire: conf.KeygenTokenTTL, AuthFunc: kloud.Stack.ValidateUser, Kite: k, } kloud.Keygen = keygen.NewServer(cfg) } else { k.Log.Warning(`disabling "keygen" methods due to missing S3/STS credentials`) } // Teams/stack handling methods. k.HandleFunc("plan", kloud.Stack.Plan) k.HandleFunc("apply", kloud.Stack.Apply) k.HandleFunc("describeStack", kloud.Stack.Status) k.HandleFunc("authenticate", kloud.Stack.Authenticate) k.HandleFunc("bootstrap", kloud.Stack.Bootstrap) k.HandleFunc("import", kloud.Stack.Import) // Credential handling. k.HandleFunc("credential.describe", kloud.Stack.CredentialDescribe) k.HandleFunc("credential.list", kloud.Stack.CredentialList) k.HandleFunc("credential.add", kloud.Stack.CredentialAdd) // Authorization handling. k.HandleFunc("auth.login", kloud.Stack.AuthLogin) k.HandleFunc("auth.passwordLogin", kloud.Stack.AuthPasswordLogin).DisableAuthentication() // Configuration handling. k.HandleFunc("config.metadata", kloud.Stack.ConfigMetadata) // Team handling. k.HandleFunc("team.list", kloud.Stack.TeamList) k.HandleFunc("team.whoami", kloud.Stack.TeamWhoami) // Machine handling. k.HandleFunc("machine.list", kloud.Stack.MachineList) // Single machine handling. k.HandleFunc("stop", kloud.Stack.Stop) k.HandleFunc("start", kloud.Stack.Start) k.HandleFunc("info", kloud.Stack.Info) k.HandleFunc("event", kloud.Stack.Event) // Klient proxy methods. k.HandleFunc("admin.add", kloud.Stack.AdminAdd) k.HandleFunc("admin.remove", kloud.Stack.AdminRemove) k.HandleHTTPFunc("/healthCheck", artifact.HealthCheckHandler(Name)) k.HandleHTTPFunc("/version", artifact.VersionHandler()) for worker, key := range authUsers { worker, key := worker, key k.Authenticators[worker] = func(r *kite.Request) error { if r.Auth.Key != key { return errors.New("wrong secret key passed, you are not authenticated") } return nil } } if conf.DebugMode { // This should be actually debug level 2. It outputs every single Kite // message and enables the kite debugging system. So enable it only if // you need it. // k.SetLogLevel(kite.DEBUG) k.Log.Info("Debug mode enabled") } if conf.TestMode { k.Log.Info("Test mode enabled") } registerURL := k.RegisterURL(!conf.Public) if conf.RegisterURL != "" { u, err := url.Parse(conf.RegisterURL) if err != nil { return nil, fmt.Errorf("Couldn't parse register url: %s", err) } registerURL = u } if err := k.RegisterForever(registerURL); err != nil { return nil, err } return kloud, nil }
func TestCollaborationChannels(t *testing.T) { tests.WithRunner(t, func(r *runner.Runner) { Convey("while testing collaboration channel", t, func() { devrim, err := models.CreateAccountInBothDbsWithNick("devrim") So(err, ShouldBeNil) So(devrim, ShouldNotBeNil) sinan, err := models.CreateAccountInBothDbsWithNick("sinan") So(err, ShouldBeNil) So(sinan, ShouldNotBeNil) groupName := models.RandomGroupName() // cretae admin user account, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(account, err) // fetch admin's session ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) groupChannel := models.CreateTypedGroupedChannelWithTest( account.Id, models.Channel_TYPE_GROUP, groupName, ) groupChannel.AddParticipant(account.Id) _, err = groupChannel.AddParticipant(devrim.Id) So(err, ShouldBeNil) _, err = groupChannel.AddParticipant(sinan.Id) So(err, ShouldBeNil) recipient, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(recipient, err) recipient2, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(recipient2, err) Convey("one can send initiate the collaboration channel with only him", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message" pmr.GroupName = groupName pmr.Recipients = []string{} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) Convey("one can send initiate the collaboration channel with 2 participants", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body message for private message @devrim @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) Convey("if group name is nil, should not fail to create collaboration channel", func() { ses, err := modelhelper.FetchOrCreateSession(sinan.Nick, "koding") So(err, ShouldBeNil) So(ses, ShouldNotBeNil) groupChannel, err := rest.CreateChannelByGroupNameAndType( sinan.Id, "koding", models.Channel_TYPE_GROUP, ses.ClientId, ) tests.ResultedWithNoErrorCheck(groupChannel, err) groupChannel.AddParticipant(devrim.Id) // ignore error groupChannel.AddParticipant(account.Id) // ignore error groupChannel.AddParticipant(sinan.Id) // ignore error pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message @devrim @sinan" pmr.GroupName = "" pmr.Recipients = []string{"devrim", "sinan"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) // we give token as parameter to SendPrivateChannelRequest // handler sets the accountId and groupname if not defined in handler's function // So it should not return any error unless account is defined Convey("if sender is not defined should not fail to create collaboration channel", func() { pmr := models.ChannelRequest{} pmr.AccountId = 0 pmr.Body = "this is a body for private message" pmr.GroupName = "" pmr.Recipients = []string{} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) Convey("one can send private message to multiple person", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"sinan"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) }) Convey("response should have created channel", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message @devrim @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(cmc.Channel.TypeConstant, ShouldEqual, models.Channel_TYPE_COLLABORATION) So(cmc.Channel.Id, ShouldBeGreaterThan, 0) So(cmc.Channel.GroupName, ShouldEqual, groupName) So(cmc.Channel.PrivacyConstant, ShouldEqual, models.Channel_PRIVACY_PRIVATE) }) Convey("send response should have participant status data", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for private message @devrim @sinan" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(cmc.IsParticipant, ShouldBeTrue) }) Convey("send response should have participant count", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is a body for @sinan private message @devrim" pmr.GroupName = groupName pmr.Recipients = []string{"devrim", "sinan"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(cmc.ParticipantCount, ShouldEqual, 3) }) Convey("send response should have participant preview", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "this is @sinan a body for @devrim private message" pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(len(cmc.ParticipantsPreview), ShouldEqual, 3) }) Convey("send response should have last Message", func() { body := "hi @devrim this is a body for private message also for @sinan" pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = body pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) So(cmc.LastMessage.Message.Body, ShouldEqual, body) }) Convey("channel messages should be listed by all recipients", func() { // // use a different group name // // in order not to interfere with another request // groupName := "testgroup" + strconv.FormatInt(rand.Int63(), 10) body := "hi @devrim this is a body for private message also for @sinan" pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = body pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cmc, ShouldNotBeNil) query := &request.Query{ AccountId: account.Id, GroupName: groupName, Type: models.Channel_TYPE_COLLABORATION, } pm, err := rest.GetPrivateChannels(query, ses.ClientId) So(err, ShouldBeNil) So(pm, ShouldNotBeNil) So(len(pm), ShouldNotEqual, 0) So(pm[0], ShouldNotBeNil) So(pm[0].Channel.TypeConstant, ShouldEqual, models.Channel_TYPE_COLLABORATION) So(pm[0].Channel.Id, ShouldEqual, cmc.Channel.Id) So(pm[0].Channel.GroupName, ShouldEqual, cmc.Channel.GroupName) So(pm[0].LastMessage.Message.Body, ShouldEqual, cmc.LastMessage.Message.Body) So(pm[0].Channel.PrivacyConstant, ShouldEqual, models.Channel_PRIVACY_PRIVATE) So(len(pm[0].ParticipantsPreview), ShouldEqual, 3) So(pm[0].IsParticipant, ShouldBeTrue) }) Convey("user should be able to search collaboration channels via purpose field", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "search collaboration channel" pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} pmr.Purpose = "test me up" pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cmc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) query := request.Query{ AccountId: account.Id, GroupName: groupName, Type: models.Channel_TYPE_COLLABORATION, } _, err = rest.SearchPrivateChannels(&query, ses.ClientId) So(err, ShouldNotBeNil) query.Name = "test" pm, err := rest.SearchPrivateChannels(&query, ses.ClientId) So(err, ShouldBeNil) So(pm, ShouldNotBeNil) So(len(pm), ShouldNotEqual, 0) So(pm[0], ShouldNotBeNil) So(pm[0].Channel.TypeConstant, ShouldEqual, models.Channel_TYPE_COLLABORATION) So(pm[0].Channel.Id, ShouldEqual, cmc.Channel.Id) So(pm[0].Channel.GroupName, ShouldEqual, cmc.Channel.GroupName) So(pm[0].LastMessage.Message.Body, ShouldEqual, cmc.LastMessage.Message.Body) So(pm[0].Channel.PrivacyConstant, ShouldEqual, models.Channel_PRIVACY_PRIVATE) So(pm[0].IsParticipant, ShouldBeTrue) }) Convey("user join activity should be listed by recipients", func() { groupName := models.RandomGroupName() // cretae admin user account, err := models.CreateAccountInBothDbs() tests.ResultedWithNoErrorCheck(account, err) // fetch admin's session ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) groupChannel := models.CreateTypedGroupedChannelWithTest( account.Id, models.Channel_TYPE_GROUP, groupName, ) So(groupChannel, ShouldNotBeNil) _, err = groupChannel.AddParticipant(account.Id) So(err, ShouldBeNil) _, err = groupChannel.AddParticipant(devrim.Id) So(err, ShouldBeNil) _, err = groupChannel.AddParticipant(sinan.Id) So(err, ShouldBeNil) _, err = groupChannel.AddParticipant(recipient.Id) So(err, ShouldBeNil) pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "test collaboration channel participants" pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cc, ShouldNotBeNil) history, err := rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 2) // add participant _, err = rest.AddChannelParticipant(cc.Channel.Id, ses.ClientId, recipient.Id) So(err, ShouldBeNil) history, err = rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 3) So(history.MessageList[0].Message, ShouldNotBeNil) So(history.MessageList[0].Message.TypeConstant, ShouldEqual, models.ChannelMessage_TYPE_SYSTEM) So(history.MessageList[0].Message.Payload, ShouldNotBeNil) addedBy, ok := history.MessageList[0].Message.Payload["addedBy"] So(ok, ShouldBeTrue) So(*addedBy, ShouldEqual, account.Nick) systemType, ok := history.MessageList[0].Message.Payload["systemType"] So(ok, ShouldBeTrue) So(*systemType, ShouldEqual, models.ChannelRequestMessage_TYPE_JOIN) // try to add same participant _, err = rest.AddChannelParticipant(cc.Channel.Id, ses.ClientId, recipient.Id) So(err, ShouldBeNil) history, err = rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 3) }) Convey("user should not be able to edit join messages", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "test collaboration channel participants again" pmr.GroupName = groupName pmr.Recipients = []string{"devrim"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cc, ShouldNotBeNil) _, err = rest.AddChannelParticipant(cc.Channel.Id, ses.ClientId, recipient.Id) So(err, ShouldBeNil) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) history, err := rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 3) joinMessage := history.MessageList[0].Message So(joinMessage, ShouldNotBeNil) _, err = rest.UpdatePost(joinMessage, ses.ClientId) So(err, ShouldNotBeNil) }) Convey("first chat message should include initial participants", func() { pmr := models.ChannelRequest{} pmr.AccountId = account.Id pmr.Body = "test initial participation message" pmr.GroupName = groupName pmr.Recipients = []string{"sinan", "devrim"} pmr.TypeConstant = models.Channel_TYPE_COLLABORATION cc, err := rest.SendPrivateChannelRequest(pmr, ses.ClientId) So(err, ShouldBeNil) So(cc, ShouldNotBeNil) ses, err := modelhelper.FetchOrCreateSession(account.Nick, groupName) So(err, ShouldBeNil) So(ses, ShouldNotBeNil) history, err := rest.GetHistory( cc.Channel.Id, &request.Query{ AccountId: account.Id, }, ses.ClientId, ) So(err, ShouldBeNil) So(history, ShouldNotBeNil) So(len(history.MessageList), ShouldEqual, 2) joinMessage := history.MessageList[1].Message So(joinMessage.TypeConstant, ShouldEqual, models.ChannelMessage_TYPE_SYSTEM) So(joinMessage.Payload, ShouldNotBeNil) initialParticipants, ok := joinMessage.Payload["initialParticipants"] So(ok, ShouldBeTrue) systemType, ok := history.MessageList[1].Message.Payload["systemType"] So(ok, ShouldBeTrue) So(*systemType, ShouldEqual, models.ChannelRequestMessage_TYPE_INIT) participants := make([]string, 0) err = json.Unmarshal([]byte(*initialParticipants), &participants) So(err, ShouldBeNil) So(len(participants), ShouldEqual, 2) So(participants, ShouldContain, "devrim") // So(*addedBy, ShouldEqual, account.OldId) }) }) }) }