Skip to content

Commit

Permalink
Merge pull request #1 from galmail/adding-form-fields-and-file-attach…
Browse files Browse the repository at this point in the history
…ments

adding form fields and file attachments support
  • Loading branch information
snagi authored Jul 23, 2018
2 parents c0d0378 + db632fb commit 0531f52
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 14 deletions.
41 changes: 41 additions & 0 deletions features/gherkin/request-options.feature
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,47 @@ Feature: Set request options
When I send the request
Then I expect last response to have status as "200"

Scenario: Set a form field
Given I request POST method at "https://httpbin.org/anything" url
And I set "field1" field with value "value1"
When I send the request
Then I expect last response to have status as "200"

Scenario: Set multiple form fields using data table
Given I request POST method at "https://httpbin.org/anything" url
And I set fields as:
| field1 | value1 |
| field2 | value2 |
When I send the request
Then I expect last response to have status as "200"

Scenario: Attach a file using local image
Given I request POST method at "https://httpbin.org/anything" url
And I attach a file at "./resources/blank.jpg" path with name "photo"
When I send the request
Then I expect last response to have status as "200"

Scenario: Attach an image file using base64
Given I request POST method at "https://httpbin.org/anything" url
And I add an attachment with name "image" and filename as "pixel.gif" with "R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=" base64 data
When I send the request
Then I expect last response to have status as "200"

Scenario: Attach an XML file using utf-8 encoding
Given I request POST method at "https://httpbin.org/anything" url
And I add an attachment with name "myxml" and filename as "test.xml" with "utf-8" encoding using content:
"""
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Someone</to>
<from>Me</from>
<heading>Test Message</heading>
<body>This is a test message!</body>
</note>
"""
When I send the request
Then I expect last response to have status as "200"

Scenario: Use generator functions in inline js template to POST method to send data to a url
Given I request GET method at "https://httpbin.org/anything" url
And I set "header1" header as "value1"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cucumber-steps-api",
"version": "0.1.3",
"version": "0.1.4",
"description": "Cucumber step library for API testing and support functions",
"main": "index.js",
"scripts": {
Expand Down
Binary file added resources/blank.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
105 changes: 105 additions & 0 deletions spec/support/http-client.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,111 @@ describe('Http Client', () => {
});
});

it('should support sending field with name and value in request', () => {
const client = new Client(agent);
return client
.url('https://httpbin.org/anything')
.method('post')
.field('field-name', 'field-value')
.send()
.then(response => {
expect(response.status).toBe(200);
})
.catch(err => {
expect(err).toBeFalsy();
});
});

it('should support sending field as an object in request', () => {
const client = new Client(agent);
return client
.url('https://httpbin.org/anything')
.method('post')
.field({ name: 'field-name', value: 'field-value' })
.send()
.then(response => {
expect(response.status).toBe(200);
})
.catch(err => {
expect(err).toBeFalsy();
});
});

it('should support sending multiple fields in request', () => {
const client = new Client(agent);
return client
.url('https://httpbin.org/anything')
.method('post')
.field({ name: 'field1', value: 'value1' })
.field({ name: 'field2', value: 'value2' })
.send()
.then(response => {
expect(response.status).toBe(200);
})
.catch(err => {
expect(err).toBeFalsy();
});
});

it('should support sending an attachment as { name, path } in request', () => {
const client = new Client(agent);
return client
.url('https://httpbin.org/anything')
.method('post')
.attach({
name: 'photo',
path: './resources/blank.jpg'
})
.send()
.then(response => {
expect(response.status).toBe(200);
})
.catch(err => {
expect(err).toBeFalsy();
});
});

it('should support sending an attachment as { name, filename, buffer } in request', () => {
const client = new Client(agent);
const base64Image = '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigD//2Q==';
const buffer = new Buffer(base64Image, 'base64');
return client
.url('https://httpbin.org/anything')
.method('post')
.attach({
name: 'photo',
filename: 'photo.jpg',
buffer,
})
.send()
.then(response => {
expect(response.status).toBe(200);
})
.catch(err => {
expect(err).toBeFalsy();
});
});

it('should support sending multiple attachments in request', () => {
const client = new Client(agent);
const buffers = [
new Buffer('R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=', 'base64'),
new Buffer('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64'),
];
return client
.url('https://httpbin.org/anything')
.method('post')
.attach({ name: 'image1', filename: 'black.gif', buffer: buffers[0] })
.attach({ name: 'image2', filename: 'transparent.gif', buffer: buffers[1] })
.send()
.then(response => {
expect(response.status).toBe(200);
})
.catch(err => {
expect(err).toBeFalsy();
});
});

it('should support sending accept type using header in request', () => {
const client = new Client(agent);
return client
Expand Down
33 changes: 33 additions & 0 deletions step-definitions/request-options.steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,39 @@ Given(/I set headers(?: as):/, function (dataTable) {
return this.client.headers(dataTable.rowsHash());
});

Given(/I set "([^"]+)" field (?:with value|as) "([^"]+)"/, function (name, value) {
expect(this.client).to.exist;
return this.client.field(name, value);
});
Given(/I set "([^"]+)" field (?:with content|as):/, function (name, content) {
expect(this.client).to.exist;
return this.client.field(name, content);
});
Given(/I set fields(?: as):/, function (dataTable) {
expect(dataTable, 'data dataTable').to.exist;
expect(dataTable.rows().length > 0, 'data dataTable length > 0').to.be.true;
expect(this.client).to.exist;
const fields = dataTable.raw().map(row => ({ name: row[0], value: row[1] }));
return fields.forEach(field => this.client.field(field));
});

Given(/I attach a|the file at "([^"]+)"(?: path) with name "([^"]+)"/, function (path, name) {
expect(this.client).to.exist;
return this.client.attach({ name, path });
});
Given(/I add an attachment with name "([^"]+)" (?:and|having) filename(?: as)? "([^"]+)" (?:with|using) "([^"]+)"(?:( base64)? data)/, function (name, filename, data, isBase64) {
expect(this.client).to.exist;
return this.client.attach({ name, filename, buffer: new Buffer(data, isBase64 ? 'base64' : 'utf8') });
});
Given(/I add an attachment with name "([^"]+)" (?:and|having) filename(?: as)? "([^"]+)" using "([^"]+)" buffer(?: with "([^"]+)" encoding)?/, function (name, filename, buffer, encoding) {
expect(this.client).to.exist;
return this.client.attach({ name, filename, buffer: new Buffer(buffer, encoding || 'base64') });
});
Given(/I add an attachment with name "([^"]+)" (?:and|having) filename(?: as)? "([^"]+)"( with "([^"]+)" encoding)? using content:/, function (name, filename, encoding, content) {
expect(this.client).to.exist;
return this.client.attach({ name, filename, buffer: new Buffer(content, encoding || 'utf8') });
});

Given(/I set "([^"]+)" query param as "([^"]+)"/, function (name, value) {
expect(this.client, 'client').to.exist;
return this.client.query(`${name}=${encodeURIComponent(value)}`);
Expand Down
77 changes: 64 additions & 13 deletions support/http-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ class RequestDefaults {
const list = Array.isArray(headers)
? headers
: Object.keys(headers).map(key => ({
name: key,
value: headers[key],
}));
name: key,
value: headers[key],
}));
list.forEach(header => this.header(header.name, header.value));
}
return this;
Expand All @@ -76,7 +76,7 @@ class RequestDefaults {
queries(queries) {
if (queries && queries.length) {
this.$queries = this.$queries.concat(
queries.map(query => {
queries.map((query) => {
if (typeof query === 'object' && Array.isArray(query)) {
return [query[0], encodeURIComponent(query[1])].join('=');
} else if (typeof query === 'object') {
Expand Down Expand Up @@ -125,6 +125,8 @@ class RequestOptions extends RequestDefaults {
this.$method = options.method;
this.$url = options.url;
this.$defaults = defaults || GlobalRequestDefaults;
this.$fields = [];
this.$attachments = [];
}

get defaults() {
Expand Down Expand Up @@ -161,6 +163,20 @@ class RequestOptions extends RequestDefaults {
return this;
}

field(field) {
if (field) {
this.$fields.push(field);
}
return this;
}

attach(attachment) {
if (attachment) {
this.$attachments.push(attachment);
}
return this;
}

dump(kind, wrap) {
const lines = [];

Expand Down Expand Up @@ -222,7 +238,7 @@ class RequestOptions extends RequestDefaults {
`-d ${
typeof this.$body === 'object'
? JSON.stringify(this.$body)
: this.$body.toString()
: this.$body && this.$body.toString()
}`
);
}
Expand Down Expand Up @@ -296,12 +312,22 @@ class HttpClient {
this.$request.queries(queries);
return this;
}

body(body) {
this.$request.body(body);
return this;
}

field(name, value) {
if (typeof name === 'object') {
this.$request.field(name);
} else {
this.$request.field({ name, value });
}
return this;
}
attach(attachment) {
this.$request.attach(attachment);
return this;
}
key(key) {
this.$request.key(key);
return this;
Expand Down Expand Up @@ -349,12 +375,12 @@ class HttpClient {
this.$request.$defaults.$headers &&
this.$request.$defaults.$headers.length
) {
this.$request.$defaults.$headers.forEach(header => {
this.$request.$defaults.$headers.forEach((header) => {
client = client.set(header.name, header.value);
});
}
if (this.$request.$headers && this.$request.$headers.length) {
this.$request.$headers.forEach(header => {
this.$request.$headers.forEach((header) => {
client = client.set(header.name, header.value);
});
}
Expand All @@ -372,12 +398,12 @@ class HttpClient {
this.$request.$defaults.$queries &&
this.$request.$defaults.$queries.length
) {
this.$request.$defaults.$queries.forEach(query => {
this.$request.$defaults.$queries.forEach((query) => {
client = client.query(query);
});
}
if (this.$request.$queries && this.$request.$queries.length) {
this.$request.$queries.forEach(query => {
this.$request.$queries.forEach((query) => {
client = client.query(query);
});
}
Expand Down Expand Up @@ -412,14 +438,39 @@ class HttpClient {
);
}

if (
this.$request.$attachments &&
this.$request.$attachments.length &&
['post', 'put', 'patch'].includes(this.$request.$method)
) {
this.$request.$attachments.forEach((attachment) => {
if (attachment.path) {
client = client.attach(attachment.name, attachment.path);
} else {
client = client.attach(attachment.name, attachment.buffer, attachment.filename);
}
});
}

if (
this.$request.$fields &&
this.$request.$fields.length &&
['post', 'put', 'patch'].includes(this.$request.$method)
) {
this.$request.$fields.forEach((field) => {
client = client.field(field.name, field.value);
});
}

if (
this.$request.$body &&
!['get', 'head'].includes(this.$request.$method)
!['get', 'head'].includes(this.$request.$method) &&
(this.$request.$fields.length === 0 || this.$request.$attachments.length === 0)
) {
client = client.send(this.$request.$body);
}

return client.ok(() => true).then(res => {
return client.ok(() => true).then((res) => {
self.response = res;
if (self.store) {
self.store.put('last-response', res);
Expand Down

0 comments on commit 0531f52

Please sign in to comment.