mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-23 02:41:50 +03:00
6e205a3f05
refs https://github.com/TryGhost/Toolbox/issues/127 - This is an effor t to define a precise set of data needed for the UrlGenerator to function, which should help with decoupling it from the frontend routes - This is almost the last piece to free us up from the massive "router" object that has been passed around
358 lines
12 KiB
JavaScript
358 lines
12 KiB
JavaScript
const should = require('should');
|
|
const sinon = require('sinon');
|
|
const urlUtils = require('../../../../../core/shared/url-utils');
|
|
const UrlGenerator = require('../../../../../core/server/services/url/UrlGenerator');
|
|
|
|
describe('Unit: services/url/UrlGenerator', function () {
|
|
let queue;
|
|
let router;
|
|
let urls;
|
|
let resources;
|
|
let resource;
|
|
let resource2;
|
|
|
|
beforeEach(function () {
|
|
queue = {
|
|
register: sinon.stub(),
|
|
start: sinon.stub()
|
|
};
|
|
|
|
router = {
|
|
addListener: sinon.stub(),
|
|
getResourceType: sinon.stub(),
|
|
getPermalinks: sinon.stub()
|
|
};
|
|
|
|
urls = {
|
|
add: sinon.stub(),
|
|
getByUrl: sinon.stub(),
|
|
removeResourceId: sinon.stub(),
|
|
getByGeneratorId: sinon.stub()
|
|
};
|
|
|
|
resources = {
|
|
getAllByType: sinon.stub(),
|
|
getByIdAndType: sinon.stub()
|
|
};
|
|
|
|
resource = {
|
|
reserve: sinon.stub(),
|
|
release: sinon.stub(),
|
|
isReserved: sinon.stub(),
|
|
removeAllListeners: sinon.stub(),
|
|
addListener: sinon.stub()
|
|
};
|
|
|
|
resource2 = {
|
|
reserve: sinon.stub(),
|
|
release: sinon.stub(),
|
|
isReserved: sinon.stub(),
|
|
removeAllListeners: sinon.stub(),
|
|
addListener: sinon.stub()
|
|
};
|
|
});
|
|
|
|
afterEach(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('ensure listeners', function () {
|
|
const urlGenerator = new UrlGenerator({router, queue});
|
|
|
|
queue.register.calledTwice.should.be.true();
|
|
should.not.exist(urlGenerator.filter);
|
|
});
|
|
|
|
it('routing type has filter', function () {
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
filter: 'featured:true',
|
|
queue
|
|
});
|
|
urlGenerator.filter.should.eql('featured:true');
|
|
});
|
|
|
|
it('routing type has changed', function () {
|
|
const urlGenerator = new UrlGenerator({router, queue, resources, urls});
|
|
|
|
sinon.stub(urlGenerator, '_try');
|
|
|
|
urls.getByGeneratorId.returns([
|
|
{
|
|
url: '/something/',
|
|
resource: resource
|
|
},
|
|
{
|
|
url: '/else/',
|
|
resource: resource2
|
|
}]);
|
|
|
|
resource.data = {
|
|
id: 'object-id-1'
|
|
};
|
|
|
|
resource2.data = {
|
|
id: 'object-id-1'
|
|
};
|
|
|
|
urlGenerator.regenerateResources();
|
|
|
|
urls.removeResourceId.calledTwice.should.be.true();
|
|
resource.release.calledOnce.should.be.true();
|
|
resource2.release.calledOnce.should.be.true();
|
|
urlGenerator._try.calledTwice.should.be.true();
|
|
});
|
|
|
|
describe('fn: _onInit', function () {
|
|
it('1 resource', function () {
|
|
resources.getAllByType.withArgs('posts').returns([resource]);
|
|
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
resourceType: 'posts',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
sinon.stub(urlGenerator, '_try');
|
|
|
|
urlGenerator._onInit();
|
|
urlGenerator._try.calledOnce.should.be.true();
|
|
});
|
|
|
|
it('no resource', function () {
|
|
resources.getAllByType.withArgs('posts').returns([]);
|
|
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
resourceType: 'posts',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
sinon.stub(urlGenerator, '_try');
|
|
|
|
urlGenerator._onInit();
|
|
urlGenerator._try.called.should.be.false();
|
|
});
|
|
});
|
|
|
|
describe('fn: _onAdded', function () {
|
|
it('type is equal', function () {
|
|
resources.getByIdAndType.withArgs('posts', 1).returns(resource);
|
|
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
resourceType: 'posts',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
sinon.stub(urlGenerator, '_try');
|
|
|
|
urlGenerator._onAdded({id: 1, type: 'posts'});
|
|
urlGenerator._try.calledOnce.should.be.true();
|
|
});
|
|
|
|
it('type is not equal', function () {
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
resourceType: 'pages',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
sinon.stub(urlGenerator, '_try');
|
|
|
|
urlGenerator._onAdded({id: 1, type: 'posts'});
|
|
urlGenerator._try.called.should.be.false();
|
|
});
|
|
});
|
|
|
|
describe('fn: _try', function () {
|
|
describe('no filter', function () {
|
|
it('resource is not taken', function () {
|
|
resource.isReserved.returns(false);
|
|
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
resourceType: 'posts',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
should.not.exist(urlGenerator.nql);
|
|
|
|
sinon.stub(urlGenerator, '_generateUrl').returns('something');
|
|
sinon.stub(urlGenerator, '_resourceListeners');
|
|
|
|
urlGenerator._try(resource);
|
|
|
|
urlGenerator._generateUrl.calledOnce.should.be.true();
|
|
urlGenerator._resourceListeners.calledOnce.should.be.true();
|
|
urls.add.calledOnce.should.be.true();
|
|
resource.reserve.calledOnce.should.be.true();
|
|
});
|
|
|
|
it('resource is taken', function () {
|
|
router.getResourceType.returns('posts');
|
|
resource.isReserved.returns(true);
|
|
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
resourceType: 'posts',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
should.not.exist(urlGenerator.nql);
|
|
|
|
sinon.stub(urlGenerator, '_generateUrl').returns('something');
|
|
sinon.stub(urlGenerator, '_resourceListeners');
|
|
|
|
urlGenerator._try(resource);
|
|
|
|
urlGenerator._generateUrl.called.should.be.false();
|
|
urlGenerator._resourceListeners.called.should.be.false();
|
|
urls.add.called.should.be.false();
|
|
resource.reserve.called.should.be.false();
|
|
});
|
|
});
|
|
|
|
describe('custom filter', function () {
|
|
it('matches', function () {
|
|
resource.isReserved.returns(false);
|
|
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
filter: 'featured:true',
|
|
resourceType: 'posts',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
sinon.stub(urlGenerator.nql, 'queryJSON').returns(true);
|
|
|
|
sinon.stub(urlGenerator, '_generateUrl').returns('something');
|
|
sinon.stub(urlGenerator, '_resourceListeners');
|
|
|
|
urlGenerator._try(resource);
|
|
|
|
urlGenerator._generateUrl.calledOnce.should.be.true();
|
|
urlGenerator._resourceListeners.calledOnce.should.be.true();
|
|
urls.add.calledOnce.should.be.true();
|
|
resource.reserve.calledOnce.should.be.true();
|
|
urlGenerator.nql.queryJSON.called.should.be.true();
|
|
});
|
|
|
|
it('no match', function () {
|
|
resource.isReserved.returns(false);
|
|
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
filter: 'featured:true',
|
|
resourceType: 'posts',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
sinon.stub(urlGenerator.nql, 'queryJSON').returns(false);
|
|
|
|
sinon.stub(urlGenerator, '_generateUrl').returns('something');
|
|
sinon.stub(urlGenerator, '_resourceListeners');
|
|
|
|
urlGenerator._try(resource);
|
|
|
|
urlGenerator._generateUrl.calledOnce.should.be.true();
|
|
urlGenerator._resourceListeners.called.should.be.false();
|
|
urls.add.called.should.be.false();
|
|
resource.reserve.called.should.be.false();
|
|
urlGenerator.nql.queryJSON.called.should.be.true();
|
|
});
|
|
|
|
it('resource is taken', function () {
|
|
resource.isReserved.returns(true);
|
|
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
filter: 'featured:true',
|
|
resourceType: 'posts',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
sinon.stub(urlGenerator.nql, 'queryJSON').returns(true);
|
|
|
|
sinon.stub(urlGenerator, '_generateUrl').returns('something');
|
|
sinon.stub(urlGenerator, '_resourceListeners');
|
|
|
|
urlGenerator._try(resource);
|
|
|
|
urlGenerator._generateUrl.called.should.be.false();
|
|
urlGenerator._resourceListeners.called.should.be.false();
|
|
urls.add.called.should.be.false();
|
|
resource.reserve.called.should.be.false();
|
|
urlGenerator.nql.queryJSON.called.should.be.false();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('fn: _generateUrl', function () {
|
|
it('returns url', function () {
|
|
const urlGenerator = new UrlGenerator({
|
|
router,
|
|
permalink: '/:slug/',
|
|
queue,
|
|
resources,
|
|
urls
|
|
});
|
|
const replacePermalink = sinon.stub().returns('/url/');
|
|
sinon.stub(urlUtils, 'replacePermalink').get(() => replacePermalink);
|
|
|
|
urlGenerator._generateUrl(resource).should.eql('/url/');
|
|
replacePermalink.calledWith('/:slug/', resource.data).should.be.true();
|
|
});
|
|
});
|
|
|
|
describe('fn: _resourceListeners', function () {
|
|
it('ensure events', function () {
|
|
const urlGenerator = new UrlGenerator({router, queue, resources, urls});
|
|
|
|
urlGenerator._resourceListeners(resource);
|
|
resource.removeAllListeners.calledOnce.should.be.true();
|
|
resource.addListener.calledTwice.should.be.true();
|
|
});
|
|
|
|
it('resource was updated', function () {
|
|
const urlGenerator = new UrlGenerator({router, queue, resources, urls});
|
|
sinon.stub(urlGenerator, '_generateUrl').returns('/welcome/');
|
|
sinon.stub(urlGenerator, '_try').returns(true);
|
|
|
|
resource.data = {
|
|
id: 'object-id'
|
|
};
|
|
|
|
urlGenerator._resourceListeners(resource);
|
|
resource.addListener.args[0][1](resource);
|
|
|
|
urlGenerator._try.called.should.be.false();
|
|
urls.removeResourceId.called.should.be.true();
|
|
resource.release.called.should.be.true();
|
|
queue.start.called.should.be.true();
|
|
});
|
|
|
|
it('resource got removed', function () {
|
|
const urlGenerator = new UrlGenerator({router, queue, resources, urls});
|
|
urlGenerator._resourceListeners(resource);
|
|
|
|
resource.data = {
|
|
id: 'object-id'
|
|
};
|
|
|
|
resource.addListener.args[1][1](resource);
|
|
urls.removeResourceId.calledOnce.should.be.true();
|
|
resource.release.calledOnce.should.be.true();
|
|
});
|
|
});
|
|
});
|