diff --git a/test/features/imap/message/delete_trash.feature b/test/features/imap/message/delete_from_trash.feature similarity index 100% rename from test/features/imap/message/delete_trash.feature rename to test/features/imap/message/delete_from_trash.feature diff --git a/test/features/imap/message/move_outlook.feature b/test/features/imap/message/move_outlook.feature deleted file mode 100644 index 1512f06b..00000000 --- a/test/features/imap/message/move_outlook.feature +++ /dev/null @@ -1,31 +0,0 @@ -Feature: IMAP move messages like Outlook - Background: - Given there is connected user "user" - And there is "user" with mailbox "Folders/mbox" - And there are messages in mailbox "INBOX" for "user" - | from | to | subject | body | - | john.doe@mail.com | user@pm.me | foo | hello | - | jane.doe@mail.com | name@pm.me | bar | world | - And there is IMAP client logged in as "user" - And there is IMAP client selected in "INBOX" - - Scenario: Move message from INBOX to mailbox like outlook - When IMAP client moves messages "2" to "" like Outlook for "user" - Then IMAP response is "OK" - And mailbox "INBOX" for "user" has messages - | from | to | subject | - | jane.doe@mail.com | name@pm.me | bar | - And mailbox "" for "user" has messages - | from | to | subject | - | john.doe@mail.com | user@pm.me | foo | - - Examples: - | mailbox | - | Archive | - | Folders/mbox | - | Spam | - | Trash | - - - - #Scenario: Move message from Trash/Spam to INBOX like outlook diff --git a/test/features/imap/message/move_without_support.feature b/test/features/imap/message/move_without_support.feature new file mode 100644 index 00000000..db8ec5da --- /dev/null +++ b/test/features/imap/message/move_without_support.feature @@ -0,0 +1,60 @@ +Feature: IMAP move messages by append and delete (without MOVE support, e.g., Outlook) + Background: + Given there is connected user "user" + And there is "user" with mailbox "Folders/mbox" + And there is IMAP client "source" logged in as "user" + And there is IMAP client "target" logged in as "user" + + Scenario Outline: Move message from INBOX to mailbox by append and delete + # Messages are inserted in opposite way to keep increasing ID. + # Sequence numbers are then opposite than listed below. + Given there are messages in mailbox "INBOX" for "user" + | from | to | subject | body | + | john.doe@mail.com | user@pm.me | foo | hello | + | jane.doe@mail.com | name@pm.me | bar | world | + And there is IMAP client "source" selected in "INBOX" + And there is IMAP client "target" selected in "" + When IMAP clients "source" and "target" move message "1" of "user" from "INBOX" to "" by append and delete + Then IMAP response to "source" is "OK" + Then IMAP response to "target" is "OK" + When IMAP client "source" sends expunge + Then IMAP response to "source" is "OK" + And mailbox "INBOX" for "user" has messages + | from | to | subject | + | john.doe@mail.com | user@pm.me | foo | + And mailbox "" for "user" has messages + | from | to | subject | + | jane.doe@mail.com | name@pm.me | bar | + + Examples: + | mailbox | + | Archive | + | Folders/mbox | + | Spam | + | Trash | + + Scenario Outline: Move message from Trash/Spam to INBOX by append and delete + # Messages are inserted in opposite way to keep increasing ID. + # Sequence numbers are then opposite than listed below. + Given there are messages in mailbox "" for "user" + | from | to | subject | body | + | john.doe@mail.com | user@pm.me | foo | hello | + | jane.doe@mail.com | name@pm.me | bar | world | + And there is IMAP client "source" selected in "" + And there is IMAP client "target" selected in "INBOX" + When IMAP clients "source" and "target" move message "1" of "user" from "" to "INBOX" by append and delete + Then IMAP response to "source" is "OK" + Then IMAP response to "target" is "OK" + When IMAP client "source" sends expunge + Then IMAP response to "source" is "OK" + And mailbox "INBOX" for "user" has messages + | from | to | subject | + | jane.doe@mail.com | name@pm.me | bar | + And mailbox "" for "user" has messages + | from | to | subject | + | john.doe@mail.com | user@pm.me | foo | + + Examples: + | mailbox | + | Spam | + | Trash | diff --git a/test/imap_actions_messages_test.go b/test/imap_actions_messages_test.go index 9e6a38bc..18107d0c 100644 --- a/test/imap_actions_messages_test.go +++ b/test/imap_actions_messages_test.go @@ -19,6 +19,7 @@ package tests import ( "fmt" + "strconv" "sync" "github.com/cucumber/godog" @@ -33,7 +34,7 @@ func IMAPActionsMessagesFeatureContext(s *godog.Suite) { s.Step(`^IMAP client searches for "([^"]*)"$`, imapClientSearchesFor) s.Step(`^IMAP client copies messages "([^"]*)" to "([^"]*)"$`, imapClientCopiesMessagesTo) s.Step(`^IMAP client moves messages "([^"]*)" to "([^"]*)"$`, imapClientMovesMessagesTo) - s.Step(`^IMAP client moves messages "([^"]*)" to "([^"]*)" like outlook$`, imapClientMovesMessagesToLikeOutlook) + s.Step(`^IMAP clients "([^"]*)" and "([^"]*)" move message "([^"]*)" of "([^"]*)" from "([^"]*)" to "([^"]*)" by append and delete$`, imapClientsMoveMessageOfUserFromToByAppendAndDelete) s.Step(`^IMAP client imports message to "([^"]*)"$`, imapClientCreatesMessage) s.Step(`^IMAP client imports message to "([^"]*)" with encoding "([^"]*)"$`, imapClientCreatesMessageWithEncoding) s.Step(`^IMAP client creates message "([^"]*)" from "([^"]*)" to "([^"]*)" with body "([^"]*)" in "([^"]*)"$`, imapClientCreatesMessageFromToWithBody) @@ -95,45 +96,51 @@ func imapClientMovesMessagesTo(messageRange, newMailboxName string) error { return nil } -func imapClientMovesMessagesToLikeOutlook(messageRange, newMailboxName, user string) error { - sourceClient := "imap" - fetchResp := ctx.GetIMAPClient(sourceClient).Fetch(messageRange, "body.peek[]") - fetchResp.AssertOK() - if err := ctx.GetTestingError(); err != nil { - return err +func imapClientsMoveMessageOfUserFromToByAppendAndDelete(sourceIMAPClient, targetIMAPClient, messageUID, bddUserID, sourceMailboxName, targetMailboxName string) error { + account := ctx.GetTestAccount(bddUserID) + if account == nil { + return godog.ErrPending + } + sourceMailbox, err := ctx.GetStoreMailbox(account.Username(), account.AddressID(), sourceMailboxName) + if err != nil { + return internalError(err, "getting store mailbox") + } + uid, err := strconv.ParseUint(messageUID, 10, 32) + if err != nil { + return internalError(err, "parsing message UID") + } + apiIDs, err := sourceMailbox.GetAPIIDsFromUIDRange(uint32(uid), uint32(uid)) + if err != nil { + return internalError(err, "getting API IDs from sequence range") + } + message, err := sourceMailbox.GetMessage(apiIDs[0]) + if err != nil { + return internalError(err, "getting message by ID") } - targetClient := "target" - if err := thereIsIMAPClientNamedLoggedInAs(targetClient, user); err != nil { - return err - } - if err := thereIsIMAPClientNamedSelectedIn(targetClient, newMailboxName); err != nil { - return err - } - - movingLikeOutlook := sync.WaitGroup{} - movingLikeOutlook.Add(2) + wg := sync.WaitGroup{} + wg.Add(2) go func() { - defer movingLikeOutlook.Done() - for _, msg := range fetchResp.Sections() { - res := ctx.GetIMAPClient(targetClient).Append(newMailboxName, msg) - res.AssertOK() - } + defer wg.Done() + msg := message.Message() + _ = imapClientNamedCreatesMessageFromToWithBody( + targetIMAPClient, + msg.Subject, + msg.Sender.String(), + msg.ToList[0].String(), + msg.Body, + targetMailboxName, + ) }() go func() { - defer movingLikeOutlook.Done() - imapClientNamedMarksMessageAsDeleted(sourceClient, messageRange) - ctx.GetIMAPLastResponse(sourceClient).AssertOK() + defer wg.Done() + _ = imapClientNamedMarksMessageAsDeleted(sourceIMAPClient, messageUID) }() - movingLikeOutlook.Wait() - - imapClientExpunge() - ctx.GetIMAPLastResponse(sourceClient).AssertOK() - - return ctx.GetTestingError() + wg.Wait() + return nil } func imapClientCreatesMessage(mailboxName string, message *gherkin.DocString) error { @@ -162,8 +169,12 @@ func imapClientCreatesMessageWithEncoding(mailboxName, encodingName string, mess } func imapClientCreatesMessageFromToWithBody(subject, from, to, body, mailboxName string) error { - res := ctx.GetIMAPClient("imap").AppendBody(mailboxName, subject, from, to, body) - ctx.SetIMAPLastResponse("imap", res) + return imapClientNamedCreatesMessageFromToWithBody("imap", subject, from, to, body, mailboxName) +} + +func imapClientNamedCreatesMessageFromToWithBody(imapClient, subject, from, to, body, mailboxName string) error { + res := ctx.GetIMAPClient(imapClient).AppendBody(mailboxName, subject, from, to, body) + ctx.SetIMAPLastResponse(imapClient, res) return nil } diff --git a/test/mocks/imap_response.go b/test/mocks/imap_response.go index 3911fe30..75c36e7c 100644 --- a/test/mocks/imap_response.go +++ b/test/mocks/imap_response.go @@ -37,8 +37,6 @@ type IMAPResponse struct { done bool } -func (ir *IMAPResponse) Sections() []string { return ir.sections } - func (ir *IMAPResponse) sendCommand(reqTag string, reqIndex int, command string, debug *debug, conn io.Writer, response *bufio.Reader) { defer func() { ir.done = true }()