-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(assets): EN-7240: Add Customer Asset support. (#96)
Signed-off-by: Jeff Cuevas-Koch <[email protected]> Co-authored-by: Jeff Cuevas-Koch <[email protected]>
- Loading branch information
1 parent
1d1fa18
commit 2c315f1
Showing
9 changed files
with
379 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import chai from 'chai'; | ||
import chaiAsPromised from 'chai-as-promised'; | ||
import fetchMock from 'fetch-mock'; | ||
import Track from '../index'; | ||
import { charlie, assets as mockAssets } from '../mocks'; | ||
|
||
chai.should(); | ||
chai.use(chaiAsPromised); | ||
|
||
describe('When searching for assets by name', () => { | ||
const api = new Track({ autoRenew: false }); | ||
|
||
beforeEach(() => charlie.setUpSuccessfulMock(api.client)); | ||
beforeEach(() => mockAssets.setUpSuccessfulMock(api.client)); | ||
beforeEach(() => fetchMock.catch(503)); | ||
afterEach(fetchMock.restore); | ||
|
||
it('should get a list of assets', () => { | ||
api.logIn({ username: '[email protected]', password: 'securepassword' }); | ||
|
||
const assetsPromise = api.customer('SYNC').assets() | ||
.getPage() | ||
.then(page => page.list) | ||
.then(assets => assets); // Do things with list of assets | ||
|
||
return assetsPromise; | ||
}); | ||
}); | ||
|
||
describe('When retrieving an asset by ID', () => { | ||
const api = new Track({ autoRenew: false }); | ||
|
||
beforeEach(() => charlie.setUpSuccessfulMock(api.client)); | ||
beforeEach(() => mockAssets.setUpSuccessfulMock(api.client)); | ||
beforeEach(() => fetchMock.catch(503)); | ||
afterEach(fetchMock.restore); | ||
|
||
it('should get an asset', () => { | ||
api.logIn({ username: '[email protected]', password: 'securepassword' }); | ||
|
||
const assetPromise = api.customer('SYNC').asset(1) | ||
.fetch() | ||
.then(asset => asset); // Do things with asset | ||
|
||
return assetPromise; | ||
}); | ||
}); | ||
|
||
describe('When creating an asset', () => { | ||
const api = new Track({ autoRenew: false }); | ||
|
||
beforeEach(() => charlie.setUpSuccessfulMock(api.client)); | ||
beforeEach(() => mockAssets.setUpSuccessfulMock(api.client)); | ||
beforeEach(() => fetchMock.catch(503)); | ||
afterEach(fetchMock.restore); | ||
|
||
it('should create an asset', () => { | ||
api.logIn({ username: '[email protected]', password: 'securepassword' }); | ||
|
||
const assetPromise = api.customer('SYNC').asset({ | ||
base64_data: 'some_data', | ||
asset_type: 'Logo', | ||
filename: 'logo.png', | ||
}) | ||
.create() | ||
.then(asset => asset); // Do things with asset | ||
|
||
return assetPromise; | ||
}); | ||
}); | ||
|
||
describe('When marking an asset saved', () => { | ||
const api = new Track({ autoRenew: false }); | ||
|
||
beforeEach(() => charlie.setUpSuccessfulMock(api.client)); | ||
beforeEach(() => mockAssets.setUpSuccessfulMock(api.client)); | ||
beforeEach(() => fetchMock.catch(503)); | ||
afterEach(fetchMock.restore); | ||
|
||
it('should mark the asset saved', () => { | ||
api.logIn({ username: '[email protected]', password: 'securepassword' }); | ||
|
||
const assetPromise = api.customer('SYNC').asset(1) | ||
.fetch() | ||
.then(asset => asset.markSaved()); | ||
|
||
return assetPromise; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import fetchMock from 'fetch-mock'; | ||
import Client from '../Client'; | ||
|
||
const assets = { | ||
setUpSuccessfulMock: (client) => { | ||
const listResponse = () => new Response( | ||
Client.toBlob(assets.list), { | ||
headers: { | ||
Link: '</1/SYNC/assets?page=1&per_page=10&sort=>; rel="next", </1/SYNC/assets?page=1&per_page=10&sort=>; rel="last"', | ||
}, | ||
}); | ||
const singleResponse = () => new Response(Client.toBlob(assets.getById(1))); | ||
const postResponse = () => new Response(undefined, { | ||
headers: { | ||
Location: '/1/SYNC/assets/1', | ||
}, | ||
}); | ||
const patchResponse = () => new Response(undefined, { | ||
headers: {}, | ||
}); | ||
|
||
fetchMock | ||
.get(client.resolve('/1/SYNC/assets?page=1&per_page=10&sort='), listResponse) | ||
.get(client.resolve('/1/SYNC/assets/1'), singleResponse) | ||
.post(client.resolve('/1/SYNC/assets'), postResponse) | ||
.patch(client.resolve('/1/SYNC/assets/1'), patchResponse); | ||
}, | ||
getById: id => assets.list.find(v => v.id === id), | ||
list: [{ | ||
href: '/1/SYNC/assets/1', | ||
id: 1, | ||
is_saved: true, | ||
url: "http://example.com/file.png", | ||
asset_type: "Logo", | ||
}], | ||
}; | ||
|
||
export default assets; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import Resource from './Resource'; | ||
|
||
/** | ||
* Asset resource | ||
*/ | ||
class Asset extends Resource { | ||
/** | ||
* Creates a new Asset. | ||
* | ||
* @param {Client} client Instance of pre-configured client | ||
* @param {Array} rest Remaining arguments to use in assigning values to this instance | ||
*/ | ||
constructor(client, ...rest) { | ||
super(client); | ||
|
||
const newProperties = Object.assign({}, ...rest); | ||
const hydrated = !Object.keys(newProperties).every(k => k === 'href' || k === 'code'); | ||
|
||
Object.assign(this, newProperties, { | ||
hydrated, | ||
}); | ||
} | ||
|
||
/** | ||
* Makes a href for a given customer code and ID | ||
* @param {string} customerCode Customer code | ||
* @param {number} id Asset ID | ||
* @returns {{href: string}} URI to instance of asset | ||
*/ | ||
static makeHref(customerCode, id) { | ||
return { | ||
href: `/1/${customerCode}/assets/${id}`, | ||
code: customerCode, | ||
}; | ||
} | ||
|
||
/** | ||
* Fetches the data for this asset via the client | ||
* @returns {Promise} If successful, a hydrated instance of this asset | ||
*/ | ||
fetch() { | ||
return this.client.get(this.href) | ||
.then(response => response.json()) | ||
.then(asset => new Asset(this.client, this, asset)); | ||
} | ||
|
||
/** | ||
* Saves data for a new asset via the client | ||
* @returns {Promise} if successful, returns an asset with the id property set | ||
*/ | ||
create() { | ||
// eslint-disable-next-line no-unused-vars | ||
const { client, hydrated, code, ...body } = this; | ||
return this.client.post(`/1/${this.code}/assets`, { body }) | ||
.then(response => response.headers.get('location')) | ||
.then((href) => { | ||
const match = /\/\d+\/\S+\/assets\/(\d+)/.exec(href); | ||
return new Asset(this.client, { ...this, href, id: parseFloat(match[1]) }); | ||
}); | ||
} | ||
|
||
/** | ||
* Updates this asset to mark it as permanently saved via the client | ||
* @returns {Promise} if successful, returns an instance of this asset | ||
*/ | ||
markSaved() { | ||
const { href } = Asset.makeHref(this.code, this.id); | ||
this.is_saved = true; | ||
return this.client.patch(href, { | ||
body: [ | ||
{ | ||
op: 'replace', | ||
path: '/is_saved', | ||
value: this.is_saved, | ||
}, | ||
], | ||
}); | ||
} | ||
} | ||
|
||
export default Asset; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import chai from 'chai'; | ||
import chaiAsPromised from 'chai-as-promised'; | ||
import fetchMock from 'fetch-mock'; | ||
import Client from '../Client'; | ||
import Asset from './Asset'; | ||
import { assets as mockAssets } from '../mocks'; | ||
|
||
chai.should(); | ||
chai.use(chaiAsPromised); | ||
|
||
describe('When instantiating an asset based on customer and ID', () => { | ||
const client = new Client(); | ||
const asset = new Asset(client, Asset.makeHref('SYNC', 1)); | ||
|
||
it('should set the href', () => asset.href.should.equal('/1/SYNC/assets/1')); | ||
it('should not be hydrated', () => asset.hydrated.should.equal(false)); | ||
}); | ||
|
||
describe('When instantiating an asset based on an object', () => { | ||
const client = new Client(); | ||
const asset = new Asset(client, mockAssets.getById(1)); | ||
|
||
it('should set the ID', () => asset.id.should.equal(1)); | ||
it('should set the href', () => asset.href.should.equal('/1/SYNC/assets/1')); | ||
it('should be hydrated', () => asset.hydrated.should.equal(true)); | ||
}); | ||
|
||
describe('When fetching an asset based on customer and ID', () => { | ||
const client = new Client(); | ||
|
||
beforeEach(() => mockAssets.setUpSuccessfulMock(client)); | ||
beforeEach(() => fetchMock.catch(503)); | ||
afterEach(fetchMock.restore); | ||
|
||
let promise; | ||
beforeEach(() => { | ||
promise = new Asset(client, Asset.makeHref('SYNC', 1)).fetch(); | ||
}); | ||
|
||
it('should resolve the promise', () => promise.should.be.fulfilled); | ||
it('should set the ID', () => promise.then(v => v.id).should.eventually.equal(1)); | ||
it('should set the href', () => promise.then(v => v.href).should.eventually.equal('/1/SYNC/assets/1')); | ||
it('should be hydrated', () => promise.then(v => v.hydrated).should.eventually.equal(true)); | ||
}); | ||
|
||
describe('When creating an asset', () => { | ||
const client = new Client(); | ||
|
||
beforeEach(() => mockAssets.setUpSuccessfulMock(client)); | ||
beforeEach(() => fetchMock.catch(503)); | ||
afterEach(fetchMock.restore); | ||
|
||
let promise; | ||
beforeEach(() => { | ||
promise = new Asset(client, { code: 'SYNC', base64_data: 'some_data' }).create(); | ||
}); | ||
|
||
it('should resolve the promise', () => promise.should.be.fulfilled); | ||
it('should set the href', () => promise.then(v => v.href).should.eventually.equal('/1/SYNC/assets/1')); | ||
it('should set the ID', () => promise.then(v => v.id).should.eventually.equal(1)); | ||
}); | ||
|
||
describe('When updating an asset', () => { | ||
const client = new Client(); | ||
|
||
beforeEach(() => mockAssets.setUpSuccessfulMock(client)); | ||
beforeEach(() => fetchMock.catch(503)); | ||
afterEach(fetchMock.restore); | ||
|
||
let promise; | ||
beforeEach(() => { | ||
promise = new Asset(client, { code: 'SYNC' }) | ||
.create() | ||
.then(asset => asset.markSaved() | ||
.then(() => asset)); | ||
}); | ||
|
||
it('should resolve the promise', () => promise.should.be.fulfilled); | ||
it('should set the href', () => promise.then(v => v.href).should.eventually.equal('/1/SYNC/assets/1')); | ||
it('should set is_saved to true', () => promise.then(v => v.is_saved).should.eventually.equal(true)); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import 'isomorphic-fetch'; | ||
import PagedContext from './PagedContext'; | ||
import Asset from './Asset'; | ||
|
||
/** | ||
* Asset querying context | ||
* | ||
* This is used to query the list of assets for a customer | ||
*/ | ||
class AssetsContext extends PagedContext { | ||
/** | ||
* Creates a new asset context | ||
* @param {Client} client Instance of pre-configured client | ||
* @param {string} customerCode Customer code | ||
* @param {object} params Object of querystring parameters to append to the URL | ||
*/ | ||
constructor(client, customerCode, params) { | ||
super(client, { ...params }); | ||
this.code = customerCode; | ||
} | ||
|
||
/** | ||
* Gets the first page of results for this context | ||
* @returns {Promise} If successful, a page of Asset objects | ||
* @see Asset | ||
*/ | ||
getPage() { | ||
return this.page(Asset, `/1/${this.code}/assets`); | ||
} | ||
} | ||
|
||
export default AssetsContext; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import chai from 'chai'; | ||
import chaiAsPromised from 'chai-as-promised'; | ||
import fetchMock from 'fetch-mock'; | ||
import Client from '../Client'; | ||
import AssetsContext from './AssetsContext'; | ||
import { assets as mockAssets } from '../mocks'; | ||
|
||
chai.should(); | ||
chai.use(chaiAsPromised); | ||
|
||
describe('When building a query for assets', () => { | ||
const client = new Client(); | ||
client.setAuthenticated(); | ||
|
||
beforeEach(() => fetchMock | ||
.get(client.resolve('/1/SYNC/assets?page=1&per_page=10&sort='), mockAssets.list) | ||
.catch(503)); | ||
afterEach(fetchMock.restore); | ||
|
||
let promise; | ||
beforeEach(() => { | ||
const assets = new AssetsContext(client, 'SYNC'); | ||
promise = assets | ||
.withPage(1) | ||
.withPerPage(10) | ||
.getPage(); | ||
}); | ||
|
||
it('should make the expected request', () => promise.should.be.fulfilled); | ||
}); |
Oops, something went wrong.