Browse Source

RPC service

Rafał Pitoń 10 years ago
parent
commit
037fdb78d2

+ 19 - 12
misago/emberapp/app/services/rpc.js

@@ -1,29 +1,34 @@
 import Ember from 'ember';
 
-export default Ember.Object.extend({
+export default Ember.Service.extend({
   ajax: function(recordOrProcedure, dataOrProcedure, data) {
-    // receive args
+    // unpack arguments
     var record = null;
     var procedure = null;
 
-    if (arguments.length === 3) {
-      record = recordOrProcedure;
-      procedure = dataOrProcedure;
-    } else {
+    if (typeof recordOrProcedure === 'string') {
       procedure = recordOrProcedure;
       data = dataOrProcedure;
+    } else {
+      record = recordOrProcedure;
+      procedure = dataOrProcedure;
+    }
+
+    var model = null;
+    if (record) {
+      model = this.store.modelFor(record.constructor);
     }
 
     // get adapter to be used for RPC
     // note: in case of Model being null this cheats adapterFor to return
     // 'adapter:application'. we are doing this, because for some reason
     // store.defaultAdapter fails to return django adapter
-    var adapter = this.store.adapterFor(record || {typeKey: 'application'});
+    var adapter = this.store.adapterFor(model || {typeKey: 'application'});
 
     // build api call URL
     var url = null;
     if (record) {
-      url = this.buildRecordProcedureURL(adapter, record, procedure);
+      url = this.buildRecordProcedureURL(adapter, model, record, procedure);
     } else {
       url = this.buildProcedureURL(adapter, procedure);
     }
@@ -32,9 +37,11 @@ export default Ember.Object.extend({
     return adapter.rpcAjax(url, data || null);
   },
 
-  buildRecordProcedureURL: function(adapter, record, procedure) {
-    var url = adapter.buildURL(record.typeKey, record.id, record);
-    return url + '/' + Ember.String.camelize(procedure);
+  buildRecordProcedureURL: function(adapter, model, record, procedure) {
+    var url = adapter.buildURL(model.typeKey, record.id, record);
+    var procedureSegment = Ember.String.decamelize(procedure).replace('_', '-');
+
+    return url + procedureSegment + '/';
   },
 
   buildProcedureURL: function(adapter, procedure) {
@@ -44,7 +51,7 @@ export default Ember.Object.extend({
 
   unpluralizeUrlProcedure: function(url, procedure) {
     // decamelize name and reverse path pluralization for type for procedure
-    var decamelized = Ember.String.decamelize(procedure);
+    var decamelized = Ember.String.decamelize(procedure).replace('_', '-');
     var pluralized = Ember.String.pluralize(decamelized);
 
     return url.replace(pluralized, decamelized);

+ 174 - 0
misago/emberapp/tests/acceptance/rpc-service-test.js

@@ -0,0 +1,174 @@
+import Ember from 'ember';
+import DS from 'ember-data';
+import { module, test } from 'qunit';
+import startApp from '../helpers/start-app';
+
+var application, container, service;
+
+module('Acceptance: RPC Service', {
+  beforeEach: function() {
+    application = startApp();
+    container = application.__container__;
+    service = container.lookup('service:rpc');
+  },
+
+  afterEach: function() {
+    Ember.run(application, 'destroy');
+    Ember.$.mockjax.clear();
+  }
+});
+
+test('unpluralizeUrlProcedure fixes urls', function(assert) {
+  assert.expect(3);
+
+  var url = service.unpluralizeUrlProcedure('/some-words/', 'some-word');
+  assert.equal(url, '/some-word/');
+
+  url = service.unpluralizeUrlProcedure('/some-words/', 'someWord');
+  assert.equal(url, '/some-word/');
+
+  url = service.unpluralizeUrlProcedure('/model/some-words/', 'some-word');
+  assert.equal(url, '/model/some-word/');
+});
+
+test('buildProcedureURL builds valid url', function(assert) {
+  assert.expect(4);
+
+  var adapter = container.lookup('adapter:application');
+
+  var url = service.buildProcedureURL(adapter, 'close');
+  assert.equal(url, '/api/close/');
+
+  url = service.buildProcedureURL(adapter, 'close-thread');
+  assert.equal(url, '/api/close-thread/');
+
+  url = service.buildProcedureURL(adapter, 'closeThread');
+  assert.equal(url, '/api/close-thread/');
+
+  url = service.buildProcedureURL(adapter, 'thread/1/close');
+  assert.equal(url, '/api/thread/1/close/');
+});
+
+test('successful RPC', function(assert) {
+  assert.expect(2);
+  var done = assert.async();
+
+  Ember.$.mockjax({
+    url: '/api/some-rpc/',
+    status: 200,
+    responseText: {
+      'detail': 'it works'
+    }
+  });
+
+  service.ajax('some-rpc').then(function(data) {
+    assert.equal(data.detail, 'it works');
+  }, function() {
+    assert.fail('rpc call should pass');
+  }).finally(function() {
+    assert.ok(true, 'finally() was called');
+    done();
+  });
+});
+
+test('failed RPC', function(assert) {
+  assert.expect(2);
+  var done = assert.async();
+
+  Ember.$.mockjax({
+    url: '/api/some-rpc/',
+    status: 400,
+    responseText: {
+      'detail': 'it fails'
+    }
+  });
+
+  service.ajax('some-rpc').then(function() {
+    assert.fail('rpc call should fail');
+  }, function(jqXHR) {
+    var rejection = jqXHR.responseJSON;
+    assert.equal(rejection.detail, 'it fails');
+  }).finally(function() {
+    assert.ok(true, 'finally() was called');
+    done();
+  });
+});
+
+test('successful model RPC', function(assert) {
+  assert.expect(2);
+  var done = assert.async();
+
+  Ember.$.mockjax({
+    url: '/api/legal-pages/privacy-policy/',
+    status: 200,
+    responseText: {
+      'id': 'privacy-policy',
+      'title': '',
+      'link': '',
+      'body': ''
+    }
+  });
+
+  Ember.$.mockjax({
+    url: '/api/legal-pages/privacy-policy/some-rpc/',
+    status: 200,
+    responseText: {
+      'detail': 'it works'
+    }
+  });
+
+  Ember.run(function() {
+    var store = container.lookup('store:main');
+
+    store.find('legal-page', 'privacy-policy').then(function(record) {
+      service.ajax(record, 'some-rpc').then(function(data) {
+        assert.equal(data.detail, 'it works');
+      }, function() {
+        assert.fail('rpc call should pass');
+      }).finally(function() {
+        assert.ok(true, 'finally() was called');
+        done();
+      });
+    });
+  });
+});
+
+test('failed model RPC', function(assert) {
+  assert.expect(2);
+  var done = assert.async();
+
+  Ember.$.mockjax({
+    url: '/api/legal-pages/privacy-policy/',
+    status: 200,
+    responseText: {
+      'id': 'privacy-policy',
+      'title': '',
+      'link': '',
+      'body': ''
+    }
+  });
+
+  Ember.$.mockjax({
+    url: '/api/legal-pages/privacy-policy/some-rpc/',
+    status: 400,
+    responseText: {
+      'detail': 'it failed'
+    }
+  });
+
+  Ember.run(function() {
+    var store = container.lookup('store:main');
+
+    store.find('legal-page', 'privacy-policy').then(function(record) {
+      service.ajax(record, 'some-rpc').then(function() {
+        assert.fail('rpc call should fail');
+      }, function(jqXHR) {
+        var rejection = jqXHR.responseJSON;
+        assert.equal(rejection.detail, 'it failed');
+      }).finally(function() {
+        assert.ok(true, 'finally() was called');
+        done();
+      });
+    });
+  });
+});

+ 0 - 18
misago/emberapp/tests/unit/services/rpc-test.js

@@ -1,18 +0,0 @@
-import {
-  moduleFor,
-  test
-} from 'ember-qunit';
-
-moduleFor('service:rpc');
-
-test('unpluralizeUrlProcedure fixes urls', function(assert) {
-  assert.expect(2);
-
-  var service = this.subject();
-
-  var url = service.unpluralizeUrlProcedure('/some-words/', 'some-word');
-  assert.equal(url, '/some-word/');
-
-  url = service.unpluralizeUrlProcedure('/model/some-words/', 'some-word');
-  assert.equal(url, '/model/some-word/');
-});