cypress-mailisk 2.0.1 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -62,6 +62,36 @@ cy.mailiskSearchInbox(namespace, { wait: false });
62
62
 
63
63
  For the full list of filters and their description see the [Search Inbox](/api-reference/search-inbox#request-1) endpoint reference.
64
64
 
65
+ ### cy.mailiskGetAttachment
66
+
67
+ This command retrieves attachment metadata including download URL, filename, content type, and size.
68
+
69
+ ```js
70
+ cy.mailiskGetAttachment('yournamespace', 'attachment-id').then((attachment) => {
71
+ console.log(attachment.data.filename);
72
+ console.log(attachment.data.content_type);
73
+ console.log(attachment.data.size);
74
+ });
75
+ ```
76
+
77
+ ### cy.mailiskDownloadAttachment
78
+
79
+ This command downloads the actual attachment content as a Buffer. It first retrieves the attachment metadata, then downloads the file from the provided download URL.
80
+
81
+ ```js
82
+ cy.mailiskDownloadAttachment('yournamespace', 'attachment-id').then((buffer) => {
83
+ // Save attachment to file
84
+ cy.writeFile('downloads/attachment.pdf', buffer);
85
+ });
86
+ ```
87
+
88
+ Both commands accept optional request options as a third parameter:
89
+
90
+ ```js
91
+ cy.mailiskGetAttachment('yournamespace', 'attachment-id', { timeout: 30000 });
92
+ cy.mailiskDownloadAttachment('yournamespace', 'attachment-id', { timeout: 60000 });
93
+ ```
94
+
65
95
  ### Filter by TO address
66
96
 
67
97
  The `to_addr_prefix` option allows filtering by the email's TO address. Specifically the TO address has to start with this.
@@ -108,6 +138,46 @@ cy.mailiskSearchInbox(namespace, {
108
138
 
109
139
  ## Common test cases
110
140
 
141
+ ### Working with email attachments
142
+
143
+ This example demonstrates how to search for emails with attachments and download them:
144
+
145
+ ```js
146
+ describe('Test email attachments', () => {
147
+ const namespace = 'yournamespace';
148
+ const testEmailAddr = `test.user@${namespace}.mailisk.net`;
149
+
150
+ it('Finds email with attachment and downloads it', () => {
151
+ cy.mailiskSearchInbox(namespace, {
152
+ to_addr_prefix: testEmailAddr,
153
+ subject_includes: 'invoice',
154
+ }).then((response) => {
155
+ expect(response.data).to.not.be.empty;
156
+ const email = response.data[0];
157
+
158
+ // Check if email has attachments
159
+ expect(email.attachments).to.not.be.empty;
160
+ const attachment = email.attachments[0];
161
+
162
+ // Get attachment metadata
163
+ cy.mailiskGetAttachment(attachment.id).then((attachmentData) => {
164
+ expect(attachmentData.data.filename).to.contain('.pdf');
165
+ expect(attachmentData.data.content_type).to.equal('application/pdf');
166
+
167
+ // Download the attachment
168
+ cy.mailiskDownloadAttachment(attachment.id).then((buffer) => {
169
+ // Save to downloads folder
170
+ cy.writeFile(`downloads/${attachmentData.data.filename}`, buffer);
171
+
172
+ // Verify file was downloaded
173
+ cy.readFile(`downloads/${attachmentData.data.filename}`).should('exist');
174
+ });
175
+ });
176
+ });
177
+ });
178
+ });
179
+ ```
180
+
111
181
  ### Password reset page
112
182
 
113
183
  This example demonstrates going to a password reset page, requesting a new password, receiving reset code link via email and finally setting the new password.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress-mailisk",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "Mailisk library for Cypress",
5
5
  "keywords": [
6
6
  "mailisk",
@@ -13,7 +13,10 @@
13
13
  "main": "index.js",
14
14
  "types": "src/mailiskCommands.d.ts",
15
15
  "scripts": {
16
- "tsc": "node_modules/.bin/tsc src/mailiskCommands.d.ts --types node"
16
+ "tsc": "node_modules/.bin/tsc src/mailiskCommands.d.ts --types node",
17
+ "test": "jest",
18
+ "test:watch": "jest --watch",
19
+ "test:coverage": "jest --coverage"
17
20
  },
18
21
  "peerDependencies": {
19
22
  "cypress": ">= 2.1.0"
@@ -32,6 +35,8 @@
32
35
  },
33
36
  "homepage": "https://github.com/mailisk-app/cypress-mailisk#readme",
34
37
  "devDependencies": {
35
- "typescript": "^4.7.4"
38
+ "typescript": "^4.7.4",
39
+ "jest": "^29.0.0",
40
+ "@jest/globals": "^29.0.0"
36
41
  }
37
42
  }
@@ -7,6 +7,17 @@ export interface EmailAddress {
7
7
  name?: string;
8
8
  }
9
9
 
10
+ export interface EmailAttachment {
11
+ /** Unique identifier for the attachment */
12
+ id: string;
13
+ /** Filename of the attachment */
14
+ filename: string;
15
+ /** Content type of the attachment */
16
+ content_type: string;
17
+ /** Size in bytes of the attachment */
18
+ size: number;
19
+ }
20
+
10
21
  export interface Email {
11
22
  /** Namespace scoped ID */
12
23
  id: string;
@@ -32,6 +43,8 @@ export interface Email {
32
43
  expires_timestamp: number;
33
44
  /** The spam score as reported by SpamAssassin */
34
45
  spam_score?: number;
46
+ /** The attachments of the email */
47
+ attachments?: EmailAttachment[];
35
48
  }
36
49
 
37
50
  export interface SearchInboxParams {
@@ -92,6 +105,17 @@ export interface SearchInboxResponse {
92
105
  data: Email[];
93
106
  }
94
107
 
108
+ export interface GetAttachmentResponse {
109
+ data: {
110
+ id: string;
111
+ filename: string;
112
+ content_type: string;
113
+ size: number;
114
+ expires_at: string | null;
115
+ download_url: string;
116
+ };
117
+ }
118
+
95
119
  declare global {
96
120
  namespace Cypress {
97
121
  interface Chainable {
@@ -111,6 +135,32 @@ declare global {
111
135
  */
112
136
  options?: Partial<Cypress.RequestOptions>,
113
137
  ): Cypress.Chainable<SearchInboxResponse>;
138
+
139
+ mailiskGetAttachment(
140
+ /**
141
+ * The attachment ID to retrieve.
142
+ */
143
+ attachmentId: string,
144
+ /**
145
+ * Request options.
146
+ *
147
+ * See https://docs.cypress.io/api/commands/request#Arguments
148
+ */
149
+ options?: Partial<Cypress.RequestOptions>,
150
+ ): Cypress.Chainable<GetAttachmentResponse>;
151
+
152
+ mailiskDownloadAttachment(
153
+ /**
154
+ * The attachment ID to download.
155
+ */
156
+ attachmentId: string,
157
+ /**
158
+ * Request options.
159
+ *
160
+ * See https://docs.cypress.io/api/commands/request#Arguments
161
+ */
162
+ options?: Partial<Cypress.RequestOptions>,
163
+ ): Cypress.Chainable<Buffer>;
114
164
  }
115
165
  }
116
166
  }
@@ -2,7 +2,7 @@ const Request = require('./request');
2
2
 
3
3
  class MailiskCommands {
4
4
  static get cypressCommands() {
5
- return ['mailiskSetApiKey', 'mailiskListNamespaces', 'mailiskSearchInbox'];
5
+ return ['mailiskSetApiKey', 'mailiskListNamespaces', 'mailiskSearchInbox', 'mailiskGetAttachment', 'mailiskDownloadAttachment'];
6
6
  }
7
7
 
8
8
  constructor() {
@@ -66,6 +66,16 @@ class MailiskCommands {
66
66
  return this.request.get(`api/emails/${namespace}/inbox?${urlParams.toString()}`, _options);
67
67
  }
68
68
  }
69
+
70
+ mailiskGetAttachment(attachmentId, options = {}) {
71
+ return this.request.get(`api/attachments/${attachmentId}`, options);
72
+ }
73
+
74
+ mailiskDownloadAttachment(attachmentId, options = {}) {
75
+ return this.mailiskGetAttachment(attachmentId, options).then((attachment) => {
76
+ return this.request.getBinary(attachment.data.download_url, options);
77
+ });
78
+ }
69
79
  }
70
80
 
71
81
  module.exports = MailiskCommands;
package/src/request.js CHANGED
@@ -81,6 +81,24 @@ class Request {
81
81
  del(path, opts) {
82
82
  return this.request('DELETE', path, undefined, opts);
83
83
  }
84
+
85
+ getBinary(url, opts) {
86
+ // For binary downloads, we need to use the full URL directly
87
+ const options = {
88
+ method: 'GET',
89
+ url: url,
90
+ encoding: null, // This tells Cypress to return binary data
91
+ ...opts,
92
+ };
93
+ options.failOnStatusCode = false;
94
+ return cy.request(options).then((response) => {
95
+ if (response.isOkStatusCode) {
96
+ return Buffer.from(response.body);
97
+ }
98
+ // Use the same error handling as regular requests
99
+ return this.getResponseHandler()(response);
100
+ });
101
+ }
84
102
  }
85
103
 
86
104
  module.exports = Request;