diff --git a/README.md b/README.md index 93203720..ae4bf2be 100644 --- a/README.md +++ b/README.md @@ -125,9 +125,11 @@ site.namespace( 'myplugin/v1' ).authors()... To create a slimmed JSON file dedicated to this particular purpose, see the Node script [lib/data/generate-endpoint-request.js](lib/data/generate-endpoint-request.js), which will let you download and save an endpoint response to your local project. +In addition to retrieving the specified resource with `.get()`, you can also `.create()`, `.update()` and `.delete()` resources: + ### Creating Posts -To create posts, use the `.post()` method on a query to POST a data object to the server (POST is the HTTP "verb" equivalent for "create"): +To create posts, use the `.create()` method on a query to POST (the HTTP verb for "create") a data object to the server: ```js // You must authenticate to be able to POST (create) a post @@ -137,7 +139,7 @@ var wp = new WP({ username: 'someusername', password: 'password' }); -wp.posts().post({ +wp.posts().create({ // "title" and "content" are the only required properties title: 'Your Post Title', content: 'Your post content', @@ -155,7 +157,7 @@ This will work in the same manner for resources other than `post`: you can see t ### Updating Posts -To create posts, use the `.put()` method on a single-item query to PUT a data object to the server (PUT is the HTTP "verb" equivalent for "update"): +To create posts, use the `.update()` method on a single-item query to PUT (the HTTP verb for "update") a data object to the server: ```js // You must authenticate to be able to PUT (update) a post @@ -166,7 +168,7 @@ var wp = new WP({ password: 'password' }); // .id() must be used to specify the post we are updating -wp.posts().id( 2501 ).post({ +wp.posts().id( 2501 ).update({ // Update the title title: 'A Better Title', // Set the post live (assuming it was "draft" before) @@ -183,13 +185,18 @@ This will work in the same manner for resources other than `post`: you can see t A WP instance object provides the following basic request methods: * `wp.posts()...`: Request items from the `/posts` endpoints -* `wp.taxonomies()...`: Generate a request against the `/taxonomies` endpoints * `wp.pages()...`: Start a request for the `/pages` endpoints -* `wp.users()...`: Get resources within the `/users` endpoints * `wp.types()...`: Get Post Type collections and objects from the `/types` endpoints +* `wp.comments()...`: Start a request for the `/comments` endpoints +* `wp.taxonomies()...`: Generate a request against the `/taxonomies` endpoints +* `wp.tags()...`: Get or create tags with the `/tags` endpoint +* `wp.categories()...`: Get or create categories with the `/categories` endpoint +* `wp.statuses()...`: Get the available statuses within the `/statuses` endpoint +* `wp.statuses()...`: Get resources within the `/statuses` endpoints +* `wp.users()...`: Get resources within the `/users` endpoints * `wp.media()...`: Get Media collections and objects from the `/media` endpoints -All of these methods return a customizable request object. The request object can be further refined with chaining methods, and/or sent to the server via `.get()`, `.post()`, `.put()`, `.delete()`, `.head()`, or `.then()`. (Not all endpoints support all methods; for example, you cannot POST or PUT records on `/types`, as these are defined in WordPress plugin or theme code.) +All of these methods return a customizable request object. The request object can be further refined with chaining methods, and/or sent to the server via `.get()`, `.create()`, `.update()`, `.delete()`, `.headers()`, or `.then()`. (Not all endpoints support all methods; for example, you cannot POST or PUT records on `/types`, as these are defined in WordPress plugin or theme code.) Additional querying methods provided, by endpoint: diff --git a/lib/constructors/wp-request.js b/lib/constructors/wp-request.js index bd5517af..5bda2a85 100644 --- a/lib/constructors/wp-request.js +++ b/lib/constructors/wp-request.js @@ -617,8 +617,8 @@ WPRequest.prototype._renderURI = function() { // Render the path to a string var path = this._renderPath(); - // If the current request supports filters, render them to a query string - var queryStr = this._renderQuery ? this._renderQuery() : ''; + // Render the query string + var queryStr = this._renderQuery(); return this._options.endpoint + path + queryStr; }; @@ -722,16 +722,17 @@ WPRequest.prototype.auth = function( usrOrObj, password ) { return this; }; -// HTTP Methods -// ============ +// HTTP Methods: Private HTTP-verb versions +// ======================================== /** - * @method get + * @method _httpGet * @async + * @private * @param {Function} [callback] A callback to invoke with the results of the GET request * @return {Promise} A promise to the results of the HTTP request */ -WPRequest.prototype.get = function( callback ) { +WPRequest.prototype._httpGet = function( callback ) { this._checkMethodSupport( 'get' ); var url = this._renderURI(); @@ -741,13 +742,15 @@ WPRequest.prototype.get = function( callback ) { }; /** - * @method post + * Invoke an HTTP "POST" request against the provided endpoint + * @method _httpPost * @async + * @private * @param {Object} data The data for the POST request * @param {Function} [callback] A callback to invoke with the results of the POST request * @return {Promise} A promise to the results of the HTTP request */ -WPRequest.prototype.post = function( data, callback ) { +WPRequest.prototype._httpPost = function( data, callback ) { this._checkMethodSupport( 'post' ); var url = this._renderURI(); data = data || {}; @@ -758,13 +761,14 @@ WPRequest.prototype.post = function( data, callback ) { }; /** - * @method put + * @method _httpPut * @async + * @private * @param {Object} data The data for the PUT request * @param {Function} [callback] A callback to invoke with the results of the PUT request * @return {Promise} A promise to the results of the HTTP request */ -WPRequest.prototype.put = function( data, callback ) { +WPRequest.prototype._httpPut = function( data, callback ) { this._checkMethodSupport( 'put' ); var url = this._renderURI(); data = data || {}; @@ -775,13 +779,14 @@ WPRequest.prototype.put = function( data, callback ) { }; /** - * @method delete + * @method _httpDelete * @async + * @private * @param {Object} [data] Data to send along with the DELETE request * @param {Function} [callback] A callback to invoke with the results of the DELETE request * @return {Promise} A promise to the results of the HTTP request */ -WPRequest.prototype.delete = function( data, callback ) { +WPRequest.prototype._httpDelete = function( data, callback ) { if ( ! callback && typeof data === 'function' ) { callback = data; data = null; @@ -794,12 +799,13 @@ WPRequest.prototype.delete = function( data, callback ) { }; /** - * @method head + * @method _httpHead * @async + * @private * @param {Function} [callback] A callback to invoke with the results of the HEAD request * @return {Promise} A promise to the header results of the HTTP request */ -WPRequest.prototype.head = function( callback ) { +WPRequest.prototype._httpHead = function( callback ) { this._checkMethodSupport( 'head' ); var url = this._renderURI(); var request = this._auth( agent.head( url ) ); @@ -807,6 +813,78 @@ WPRequest.prototype.head = function( callback ) { return invokeAndPromisify( request, callback, returnHeaders ); }; +// HTTP Methods: Public Interface +// ============================== + +/** @deprecated Use .create() */ +WPRequest.prototype.post = function( data, callback ) { + return this._httpPost( data, callback ); +}; + +/** @deprecated Use .update() */ +WPRequest.prototype.put = function( data, callback ) { + return this._httpPut( data, callback ); +}; + +/** + * @method get + * @async + * @param {Function} [callback] A callback to invoke with the results of the GET request + * @return {Promise} A promise to the results of the HTTP request + */ +WPRequest.prototype.get = function( callback ) { + return this._httpGet( callback ); +}; + +/** + * Create a HEAD request against a site + * @method headers + * @async + * @param {Function} [callback] A callback to invoke with the results of the HEAD request + * @return {Promise} A promise to the header results of the HTTP request + */ +WPRequest.prototype.headers = function( callback ) { + return this._httpHead( callback ); +}; + +/** + * Invoke an HTTP "POST" request against the provided endpoint + * + * This is the public interface creating for POST requests + * + * @method create + * @async + * @param {Object} data The data for the POST request + * @param {Function} [callback] A callback to invoke with the results of the POST request + * @return {Promise} A promise to the results of the HTTP request + */ +WPRequest.prototype.create = function( data, callback ) { + return this._httpPost( data, callback ); +}; + +/** + * @method _httpPut + * @async + * @private + * @param {Object} data The data for the PUT request + * @param {Function} [callback] A callback to invoke with the results of the PUT request + * @return {Promise} A promise to the results of the HTTP request + */ +WPRequest.prototype.update = function( data, callback ) { + return this._httpPut( data, callback ); +}; + +/** + * @method delete + * @async + * @param {Object} [data] Data to send along with the DELETE request + * @param {Function} [callback] A callback to invoke with the results of the DELETE request + * @return {Promise} A promise to the results of the HTTP request + */ +WPRequest.prototype.delete = function( data, callback ) { + return this._httpDelete( data, callback ); +}; + /** * Calling .then on a query chain will invoke the query as a GET and return a promise * @@ -817,7 +895,7 @@ WPRequest.prototype.head = function( callback ) { * @return {Promise} A promise to the results of the HTTP request */ WPRequest.prototype.then = function( successCallback, failureCallback ) { - return this.get().then( successCallback, failureCallback ); + return this._httpGet().then( successCallback, failureCallback ); }; module.exports = WPRequest; diff --git a/tests/integration/posts.js b/tests/integration/posts.js index bc2bceb9..9fb295e5 100644 --- a/tests/integration/posts.js +++ b/tests/integration/posts.js @@ -114,10 +114,10 @@ describe( 'integration: posts()', function() { return expect( prom ).to.eventually.equal( SUCCESS ); }); - it( 'include the total number of posts', function() { - var prom = wp.posts().get().then(function( posts ) { - expect( posts._paging ).to.have.property( 'total' ); - expect( posts._paging.total ).to.equal( '38' ); + it( 'include the total number of posts: use .headers() for coverage reasons', function() { + var prom = wp.posts().headers().then(function( postHeadersResponse ) { + expect( postHeadersResponse ).to.have.property( 'x-wp-total' ); + expect( postHeadersResponse[ 'x-wp-total' ] ).to.equal( '38' ); return SUCCESS; }); return expect( prom ).to.eventually.equal( SUCCESS ); @@ -301,8 +301,8 @@ describe( 'integration: posts()', function() { return expect( prom ).to.eventually.equal( SUCCESS ); }); - it( 'cannot POST (create) without authentication', function() { - var prom = wp.posts().post({ + it( 'cannot create (POST) without authentication', function() { + var prom = wp.posts().create({ title: 'New Post 2501', content: 'Some Content' }).catch(function( err ) { @@ -314,11 +314,11 @@ describe( 'integration: posts()', function() { return expect( prom ).to.eventually.equal( SUCCESS ); }); - it( 'cannot PUT (update) without authentication', function() { + it( 'cannot update (PUT) without authentication', function() { var id; var prom = wp.posts().perPage( 1 ).get().then(function( posts ) { id = posts[ 0 ].id; - return wp.posts().id( id ).put({ + return wp.posts().id( id ).update({ title: 'New Post 2501', content: 'Some Content' }); @@ -333,7 +333,7 @@ describe( 'integration: posts()', function() { it( 'can create, update & delete a post when authenticated', function() { var id; - var prom = wp.posts().auth( credentials ).post({ + var prom = wp.posts().auth( credentials ).create({ title: 'New Post 2501', content: 'Some Content' }).then(function( createdPost ) { @@ -347,7 +347,7 @@ describe( 'integration: posts()', function() { expect( createdPost ).to.have.property( 'content' ); expect( createdPost.content ).to.have.property( 'raw' ); expect( createdPost.content.raw ).to.equal( 'Some Content' ); - return wp.posts().auth( credentials ).id( id ).put({ + return wp.posts().auth( credentials ).id( id ).update({ title: 'Updated Title', status: 'publish' }); diff --git a/tests/unit/lib/constructors/wp-request.js b/tests/unit/lib/constructors/wp-request.js index 482c4ee9..bf11ac76 100644 --- a/tests/unit/lib/constructors/wp-request.js +++ b/tests/unit/lib/constructors/wp-request.js @@ -322,6 +322,19 @@ describe( 'WPRequest', function() { expect( request._options.auth ).to.be.true; }); + it( 'does not set username/password if they are not provided as string values', function() { + expect( request._options ).not.to.have.property( 'username' ); + expect( request._options ).not.to.have.property( 'password' ); + request.auth({ + username: 123, + password: false + }); + expect( request._options ).not.to.have.property( 'username' ); + expect( request._options ).not.to.have.property( 'password' ); + expect( request._options ).to.have.property( 'auth' ); + expect( request._options.auth ).to.be.true; + }); + }); // auth describe( '._auth', function() { @@ -834,4 +847,43 @@ describe( 'WPRequest', function() { }); // Pagination }); // Request methods + + describe( 'deprecated request methods', function() { + + describe( '.post()', function() { + + it( 'is a function', function() { + expect( request ).to.have.property( 'post' ); + expect( request.post ).to.be.a( 'function' ); + }); + + it( 'proxies to ._httpPost', function() { + sinon.stub( request, '_httpPost' ); + function cb() {} + request.post( 'foo', cb ); + expect( request._httpPost ).to.have.been.calledWith( 'foo', cb ); + request._httpPost.restore(); + }); + + }); + + describe( '.put()', function() { + + it( 'is a function', function() { + expect( request ).to.have.property( 'put' ); + expect( request.put ).to.be.a( 'function' ); + }); + + it( 'proxies to ._httpPut', function() { + sinon.stub( request, '_httpPut' ); + function cb() {} + request.put( 'foo', cb ); + expect( request._httpPut ).to.have.been.calledWith( 'foo', cb ); + request._httpPut.restore(); + }); + + }); + + }); // Deprecated request methods + });