mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
refs https://linear.app/tryghost/issue/CORE-104/decouple-frontend-routing-events-from-urlserver-events - The 'router.created' event should eventually be killed. For now the aim is to create a clear communication pathway between frontend's routing module and the URL service (similar to the frontend bridge concept on the "server" side)
282 lines
11 KiB
JavaScript
282 lines
11 KiB
JavaScript
const should = require('should');
|
|
const sinon = require('sinon');
|
|
const bootstrap = require('../../../../../core/frontend/services/routing/bootstrap');
|
|
const controllers = require('../../../../../core/frontend/services/routing/controllers');
|
|
const StaticRoutesRouter = require('../../../../../core/frontend/services/routing/StaticRoutesRouter');
|
|
const configUtils = require('../../../../utils/configUtils');
|
|
|
|
describe('UNIT - services/routing/StaticRoutesRouter', function () {
|
|
let req;
|
|
let res;
|
|
let next;
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
sinon.stub(bootstrap.internal, 'routerCreated');
|
|
|
|
sinon.spy(StaticRoutesRouter.prototype, 'mountRoute');
|
|
sinon.spy(StaticRoutesRouter.prototype, 'mountRouter');
|
|
|
|
req = sinon.stub();
|
|
res = sinon.stub();
|
|
next = sinon.stub();
|
|
|
|
res.locals = {};
|
|
});
|
|
|
|
afterEach(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
describe('static routes', function () {
|
|
it('instantiate: default', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/about/', {templates: ['test']});
|
|
should.exist(staticRoutesRouter.router);
|
|
|
|
should.not.exist(staticRoutesRouter.getFilter());
|
|
should.not.exist(staticRoutesRouter.getPermalinks());
|
|
|
|
staticRoutesRouter.templates.should.eql(['test']);
|
|
|
|
bootstrap.internal.routerCreated.calledOnce.should.be.true();
|
|
bootstrap.internal.routerCreated.calledWith(staticRoutesRouter).should.be.true();
|
|
|
|
staticRoutesRouter.mountRoute.callCount.should.eql(1);
|
|
|
|
// parent route
|
|
staticRoutesRouter.mountRoute.args[0][0].should.eql('/about/');
|
|
staticRoutesRouter.mountRoute.args[0][1].should.eql(controllers.static);
|
|
});
|
|
|
|
it('initialize with data+filter', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/about/', {
|
|
data: {query: {}, router: {}},
|
|
filter: 'tag:test'
|
|
});
|
|
|
|
should.exist(staticRoutesRouter.router);
|
|
|
|
should.not.exist(staticRoutesRouter.getPermalinks());
|
|
should.not.exist(staticRoutesRouter.getFilter());
|
|
staticRoutesRouter.templates.should.eql([]);
|
|
|
|
bootstrap.internal.routerCreated.calledOnce.should.be.true();
|
|
bootstrap.internal.routerCreated.calledWith(staticRoutesRouter).should.be.true();
|
|
|
|
staticRoutesRouter.mountRoute.callCount.should.eql(1);
|
|
|
|
// parent route
|
|
staticRoutesRouter.mountRoute.args[0][0].should.eql('/about/');
|
|
staticRoutesRouter.mountRoute.args[0][1].should.eql(controllers.static);
|
|
});
|
|
|
|
it('fn: _prepareStaticRouteContext', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/about/', {templates: []});
|
|
|
|
staticRoutesRouter._prepareStaticRouteContext(req, res, next);
|
|
next.called.should.be.true();
|
|
|
|
res.routerOptions.should.have.properties('type', 'templates', 'defaultTemplate', 'context', 'data', 'contentType');
|
|
res.routerOptions.type.should.eql('custom');
|
|
res.routerOptions.templates.should.eql([]);
|
|
res.routerOptions.defaultTemplate.should.be.a.Function();
|
|
res.routerOptions.context.should.eql(['about']);
|
|
res.routerOptions.data.should.eql({});
|
|
|
|
should(res.routerOptions.contentType).be.undefined();
|
|
should.not.exist(res.locals.slug);
|
|
});
|
|
|
|
it('fn: _prepareStaticRouteContext', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/', {templates: []});
|
|
|
|
staticRoutesRouter._prepareStaticRouteContext(req, res, next);
|
|
next.called.should.be.true();
|
|
|
|
res.routerOptions.should.have.properties('type', 'templates', 'defaultTemplate', 'context', 'data', 'contentType');
|
|
res.routerOptions.type.should.eql('custom');
|
|
res.routerOptions.templates.should.eql([]);
|
|
res.routerOptions.defaultTemplate.should.be.a.Function();
|
|
res.routerOptions.context.should.eql(['index']);
|
|
res.routerOptions.data.should.eql({});
|
|
|
|
should.not.exist(res.locals.slug);
|
|
});
|
|
});
|
|
|
|
describe('channels', function () {
|
|
describe('initialize', function () {
|
|
it('initialize with controller+data+filter', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/channel/', {
|
|
controller: 'channel',
|
|
data: {query: {}, router: {}},
|
|
filter: 'tag:test'
|
|
});
|
|
|
|
should.exist(staticRoutesRouter.router);
|
|
|
|
should.not.exist(staticRoutesRouter.getPermalinks());
|
|
staticRoutesRouter.getFilter().should.eql('tag:test');
|
|
staticRoutesRouter.templates.should.eql([]);
|
|
should.exist(staticRoutesRouter.data);
|
|
|
|
bootstrap.internal.routerCreated.calledOnce.should.be.true();
|
|
bootstrap.internal.routerCreated.calledWith(staticRoutesRouter).should.be.true();
|
|
|
|
staticRoutesRouter.mountRoute.callCount.should.eql(2);
|
|
|
|
// parent route
|
|
staticRoutesRouter.mountRoute.args[0][0].should.eql('/channel/');
|
|
staticRoutesRouter.mountRoute.args[0][1].should.eql(controllers.channel);
|
|
|
|
// pagination feature
|
|
staticRoutesRouter.mountRoute.args[1][0].should.eql('/channel/page/:page(\\d+)');
|
|
staticRoutesRouter.mountRoute.args[1][1].should.eql(controllers.channel);
|
|
});
|
|
|
|
it('initialize with controller+filter', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/channel/', {
|
|
controller: 'channel',
|
|
filter: 'tag:test'
|
|
});
|
|
|
|
should.exist(staticRoutesRouter.router);
|
|
|
|
should.not.exist(staticRoutesRouter.getPermalinks());
|
|
staticRoutesRouter.getFilter().should.eql('tag:test');
|
|
|
|
staticRoutesRouter.templates.should.eql([]);
|
|
|
|
bootstrap.internal.routerCreated.calledOnce.should.be.true();
|
|
bootstrap.internal.routerCreated.calledWith(staticRoutesRouter).should.be.true();
|
|
|
|
staticRoutesRouter.mountRoute.callCount.should.eql(2);
|
|
|
|
// parent route
|
|
staticRoutesRouter.mountRoute.args[0][0].should.eql('/channel/');
|
|
staticRoutesRouter.mountRoute.args[0][1].should.eql(controllers.channel);
|
|
|
|
// pagination feature
|
|
staticRoutesRouter.mountRoute.args[1][0].should.eql('/channel/page/:page(\\d+)');
|
|
staticRoutesRouter.mountRoute.args[1][1].should.eql(controllers.channel);
|
|
});
|
|
|
|
it('initialize with controller+data', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/channel/', {
|
|
controller: 'channel',
|
|
data: {query: {}, router: {}}
|
|
});
|
|
|
|
should.not.exist(staticRoutesRouter.getFilter());
|
|
});
|
|
|
|
it('initialize on subdirectory with controller+data+filter', function () {
|
|
configUtils.set('url', 'http://localhost:2366/blog/');
|
|
|
|
const staticRoutesRouter = new StaticRoutesRouter('/channel/', {
|
|
controller: 'channel',
|
|
data: {query: {}, router: {}},
|
|
filter: 'author:michi'
|
|
});
|
|
|
|
staticRoutesRouter.mountRoute.callCount.should.eql(2);
|
|
|
|
// parent route
|
|
staticRoutesRouter.mountRoute.args[0][0].should.eql('/channel/');
|
|
staticRoutesRouter.mountRoute.args[0][1].should.eql(controllers.channel);
|
|
|
|
// pagination feature
|
|
staticRoutesRouter.mountRoute.args[1][0].should.eql('/channel/page/:page(\\d+)');
|
|
staticRoutesRouter.mountRoute.args[1][1].should.eql(controllers.channel);
|
|
});
|
|
});
|
|
|
|
describe('fn: _prepareChannelContext', function () {
|
|
it('with data+filter', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/channel/', {
|
|
controller: 'channel',
|
|
data: {query: {}, router: {}},
|
|
filter: 'tag:test'
|
|
});
|
|
|
|
staticRoutesRouter._prepareChannelContext(req, res, next);
|
|
next.calledOnce.should.eql(true);
|
|
res.routerOptions.should.eql({
|
|
type: 'channel',
|
|
context: ['channel'],
|
|
filter: 'tag:test',
|
|
name: 'channel',
|
|
data: {},
|
|
limit: undefined,
|
|
order: undefined,
|
|
templates: []
|
|
});
|
|
});
|
|
|
|
it('with data', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/nothingcomparestoyou/', {
|
|
controller: 'channel',
|
|
data: {query: {type: 'read'}, router: {}}
|
|
});
|
|
|
|
staticRoutesRouter._prepareChannelContext(req, res, next);
|
|
next.calledOnce.should.eql(true);
|
|
res.routerOptions.should.eql({
|
|
type: 'channel',
|
|
context: ['nothingcomparestoyou'],
|
|
name: 'nothingcomparestoyou',
|
|
filter: undefined,
|
|
data: {type: 'read'},
|
|
limit: undefined,
|
|
order: undefined,
|
|
templates: []
|
|
});
|
|
});
|
|
|
|
it('with filter', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/channel/', {
|
|
controller: 'channel',
|
|
filter: 'tag:test'
|
|
});
|
|
|
|
staticRoutesRouter._prepareChannelContext(req, res, next);
|
|
next.calledOnce.should.eql(true);
|
|
res.routerOptions.should.eql({
|
|
type: 'channel',
|
|
context: ['channel'],
|
|
filter: 'tag:test',
|
|
name: 'channel',
|
|
limit: undefined,
|
|
order: undefined,
|
|
data: {},
|
|
templates: []
|
|
});
|
|
});
|
|
|
|
it('with order+limit', function () {
|
|
const staticRoutesRouter = new StaticRoutesRouter('/channel/', {
|
|
controller: 'channel',
|
|
filter: 'tag:test',
|
|
limit: 2,
|
|
order: 'published_at asc'
|
|
});
|
|
|
|
staticRoutesRouter._prepareChannelContext(req, res, next);
|
|
next.calledOnce.should.eql(true);
|
|
res.routerOptions.should.eql({
|
|
type: 'channel',
|
|
context: ['channel'],
|
|
filter: 'tag:test',
|
|
name: 'channel',
|
|
limit: 2,
|
|
order: 'published_at asc',
|
|
data: {},
|
|
templates: []
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|