From a1ed6749182fdc24e8f08f7eddba3a7de08e7fe4 Mon Sep 17 00:00:00 2001 From: Alex LaFroscia Date: Sun, 5 Apr 2020 13:12:45 -0400 Subject: [PATCH] feat: add decorator for `memberAction` --- addon/decorators.ts | 10 ++++ .../utils/decorators/member-action-test.ts | 52 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 addon/decorators.ts create mode 100644 tests/unit/utils/decorators/member-action-test.ts diff --git a/addon/decorators.ts b/addon/decorators.ts new file mode 100644 index 000000000..2e95e202a --- /dev/null +++ b/addon/decorators.ts @@ -0,0 +1,10 @@ +import instanceOp, { InstanceOperationOptions } from './utils/member-action'; + +export function memberAction(options: InstanceOperationOptions) { + return function createMemberActionDescriptor() { + return { + value: instanceOp(options) + }; + } +} + diff --git a/tests/unit/utils/decorators/member-action-test.ts b/tests/unit/utils/decorators/member-action-test.ts new file mode 100644 index 000000000..10ab71aa8 --- /dev/null +++ b/tests/unit/utils/decorators/member-action-test.ts @@ -0,0 +1,52 @@ +import { memberAction } from 'ember-api-actions/decorators'; +import DS from 'ember-data'; +import { setupTest } from 'ember-qunit'; +import Pretender from 'pretender'; +import { module, test } from 'qunit'; + +class Fruit extends DS.Model { + @memberAction({ path: 'doRipen' }) + public ripen; +} + +module('Unit | Utility | decorators/member-action', (hooks) => { + setupTest(hooks); + + let server: any; + hooks.beforeEach(() => { + server = new Pretender(); + }); + hooks.afterEach(() => { + server.shutdown(); + }); + + hooks.beforeEach(function() { + this.owner.unregister('model:fruit'); + this.owner.register('model:fruit', Fruit); + + this.store = this.owner.lookup('service:store'); + + this.fruit = this.store.createRecord('fruit', { + id: 1, + name: 'apple' + }); + }); + + test('it adds a method through a decorator', async function(assert) { + assert.expect(4); + + server.put('/fruits/:id/doRipen', (request: { url: string; requestBody: string }) => { + const data = JSON.parse(request.requestBody); + assert.deepEqual(data, { id: '1', name: 'apple' }, 'member action - request payload is correct'); + assert.equal(request.url, '/fruits/1/doRipen', 'request was made to "doRipen"'); + return [200, {}, '{"status": "ok"}']; + }); + + assert.equal(typeof this.fruit.ripen, 'function', 'Assigns a method on the type'); + + const { id, name } = this.fruit; + const result = await this.fruit.ripen({ id, name }); + + assert.deepEqual(result, { status: 'ok' }, 'Passes through the API response'); + }); +});