Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal - Response configuration (headers...) #156

Closed
xcambar opened this issue Dec 7, 2015 · 10 comments
Closed

Proposal - Response configuration (headers...) #156

xcambar opened this issue Dec 7, 2015 · 10 comments

Comments

@xcambar
Copy link
Contributor

xcambar commented Dec 7, 2015

Hey,
I need to send some custom headers along with the data in the response, and there's currenty no way (that I know of) to do so.

The idea below is simply to add a generic returns method to the mocks that will handle a custom configuration object, like

TestHelper.returns({
  models: [...],
  headers: {
    'X-Total-Count': 1234
  }
})

Before going deeper in the writing of that, I wanted to gather feedback and open the discussion.

Here's a quick draft of how it ould be quickly implemented:

diff --git a/addon/mock-query-request.js b/addon/mock-query-request.js
index dd256cb..2bfd1fa 100644
--- a/addon/mock-query-request.js
+++ b/addon/mock-query-request.js
@@ -27,6 +27,7 @@ var MockQueryRequest = function (url, modelName, queryParams) {
   var responseJson = FactoryGuy.getFixtureBuilder().convertForBuild(modelName, []);
   var errors = {};
   var currentQueryParams = queryParams;
+  let responseOptions = {};

   this.withParams = function (queryParams) {
     currentQueryParams = queryParams;
@@ -74,6 +75,29 @@ var MockQueryRequest = function (url, modelName, queryParams) {
     return this;
   };

+  this.returns = function (options = {}) {
+    const responseKeys = ['models', 'json', 'existingIds'].filter((k)=> options.hasOwnProperty(k));
+    Ember.assert(`[ember-data-factory-guy] You must pass only one output key to 'returns', you passed none`, responseKeys.length!== 0);
+    Ember.assert(`[ember-data-factory-guy] You must pass only one output key to 'returns',
+                 you passed ${responseKeys.length}: ${responseKeys.toString()}`, responseKeys.length === 1);
+
+    switch(responseKeys[0]) {
+      case 'models':
+        this.returnsModels(options.models);
+        break;
+      case 'json':
+        this.returnsJSON(options.json);
+        break;
+      case 'existingIds':
+        this.returnsExistingIds(options.json);
+        break;
+    }
+
+    responseOptions = Ember.merge({}, options);
+    delete responseOptions[responseKeys[0]];
+    return this;
+  };
+
   var handler = function (settings) {
     if (settings.url === url && settings.type === "GET") {
       if (succeed) {
@@ -82,9 +106,9 @@ var MockQueryRequest = function (url, modelName, queryParams) {
             return false;
           }
         }
-        return {status: 200, responseText: responseJson};
+        return Ember.merge({status: 200, responseText: responseJson}, responseOptions);
       } else {
-        return {status: status, responseText: errors};
+        return Ember.merge({status: status, responseText: errors}, responseOptions);
       }
     } else {
       return false;

What do you think?

@danielspaniel
Copy link
Collaborator

Seems like a great idea ( to add the ability for headers ) .. the rest I don't love so much ..
why not add a 'withHeaders' method and call it a day .. so easy .. so simple .. leave the rest as is.

@xcambar
Copy link
Contributor Author

xcambar commented Dec 7, 2015

withHeaders is unclear whether the headers are coming from the request or going into the response.

I kinda like the idea of a generic with method for matching the request and a generic returns that defines custom parts of the response. Names, here, are just to give an idea.

@danielspaniel
Copy link
Collaborator

yes, that is a good point .. how about returnsHeaders? kinda long winded I know.
I feel like if I have to do

mockQuery.returns({headers: "blah"}).with({models: [blah]}) 

it's actually not that much better than:

mockQuery.returnsHeaders("blah").returnsModels([blah]) 

although .. now that I look at it .. your version is not too shabby .. hmm .. pondering

@xcambar
Copy link
Contributor Author

xcambar commented Dec 7, 2015

I'll write a couple example snippets (tomorrow probably, if time allows) for a wider overview.

Meanwhile, I won't mind returnsHeaders at all, despite verbosity.

@danielspaniel
Copy link
Collaborator

Sure thing. I am starting to warm up to it. I guess I just want to have consistency around all the chainable methods for mockGet, mockCreate, etc .. if we can get a unified look .. I am all in.

@xcambar
Copy link
Contributor Author

xcambar commented Dec 8, 2015

There are currently1 4 main mock classes: Mock(Create|Get|Update|Query)Request.
Here's a rundown of their interfaces:

  1. MockCreateRequest has calculate, match, andReturn, andFail, handler
  2. MockGetRequest has andSucceed, andFail, handler
  3. MockQueryRequest has withParams, returnsModels, returnsJSON, returnsExistingIds, andFail (and upcoming returnsHeaders or equivalent)
  4. MockUpdateRequest has andSucceed, andFail, handler

Here's something that doesn't seem too much work and that, if applied, should be applied to all:

  • andSucceed/andFail everywhere (eg, simulating 500 or 404)
  • andReturn and returns* are renamed to returns (offers to customise Headers as well as payloads)
  • handler remains public for (rare) cases where you need to have full control, but it needs to be wrapped up to be changed at runtime (impossible at the moment)
  • with is added, it replaces withParams and allows to validate headers as well as params

AFAICT, this can be fully backward compatible, deprecation warnings can be added where appropriate.

Yep, no snippets, sorry, I'm being lazy right now. I'll do some or update the README examples if you require them.


1: a MockDeleteRequest will most probably be proposed one day or another

@danielspaniel
Copy link
Collaborator

Gee, your not that lazy .. it's 7 am and you are scribbling away, writing up the ideas in a way that gets the ideas across .. and gives the full overview of what is going on .. and ... me like.
If you want to do this on your own PR you can or I can do some whatever you like. But I think it all makes sense, and if backwards compatible ( which is key ) .. then it's seamless to upgrade.

@xcambar
Copy link
Contributor Author

xcambar commented Dec 8, 2015

I'm cheating, it's almost 2pm here (Berlin) ;)

I took the liberty to create the corresponding issues. That way, feel free to self-assign what you want to work on, so we don't step on each other's foot 😉

As I quickly started work on #158, I'll happily finish it.

@xcambar
Copy link
Contributor Author

xcambar commented Dec 8, 2015

And if you're ok with it, this issue can be closed, I guess.

@danielspaniel
Copy link
Collaborator

Sure thing, good idea about the separate issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants