2018-04-15 13:12:20 +03:00
/* eslint no-invalid-this:0 */
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
const _ = require ( 'lodash' ) ;
const should = require ( 'should' ) ;
const sinon = require ( 'sinon' ) ;
const Promise = require ( 'bluebird' ) ;
const testUtils = require ( '../../utils' ) ;
const knex = require ( '../../../server/data/db' ) . knex ;
const urlService = require ( '../../../server/services/url' ) ;
const schema = require ( '../../../server/data/schema' ) ;
const models = require ( '../../../server/models' ) ;
const common = require ( '../../../server/lib/common' ) ;
const security = require ( '../../../server/lib/security' ) ;
const sandbox = sinon . sandbox . create ( ) ;
2018-02-07 12:46:22 +03:00
2018-03-05 11:10:27 +03:00
describe ( 'Unit: models/post' , function ( ) {
2018-10-06 23:13:52 +03:00
const mockDb = require ( 'mock-knex' ) ;
let tracker ;
before ( function ( ) {
models . init ( ) ;
mockDb . mock ( knex ) ;
tracker = mockDb . getTracker ( ) ;
} ) ;
afterEach ( function ( ) {
sandbox . restore ( ) ;
} ) ;
after ( function ( ) {
mockDb . unmock ( knex ) ;
} ) ;
describe ( 'filter' , function ( ) {
it ( 'generates correct query for - filter: tags: [photo, video] + id: -{id},limit of: 3, with related: tags' , function ( ) {
const queries = [ ] ;
tracker . install ( ) ;
tracker . on ( 'query' , ( query ) => {
queries . push ( query ) ;
query . response ( [ ] ) ;
} ) ;
return models . Post . findPage ( {
2018-11-15 17:27:31 +03:00
filter : 'tags:[photo, video]+id:-' + testUtils . filterData . data . posts [ 3 ] . id ,
2018-10-06 23:13:52 +03:00
limit : 3 ,
withRelated : [ 'tags' ]
} ) . then ( ( ) => {
queries . length . should . eql ( 2 ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 0 ] . sql . should . eql ( 'select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`id` != ? and `posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` where `tags`.`slug` in (?, ?))) and (`posts`.`page` = ? and `posts`.`status` = ?))' ) ;
2018-10-06 23:13:52 +03:00
queries [ 0 ] . bindings . should . eql ( [
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
testUtils . filterData . data . posts [ 3 ] . id ,
2018-10-06 23:13:52 +03:00
'photo' ,
'video' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
false ,
'published'
2018-10-06 23:13:52 +03:00
] ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 1 ] . sql . should . eql ( 'select `posts`.* from `posts` where ((`posts`.`id` != ? and `posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` where `tags`.`slug` in (?, ?))) and (`posts`.`page` = ? and `posts`.`status` = ?)) order by (SELECT count(*) FROM posts_tags WHERE post_id = posts.id) DESC, CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?' ) ;
2018-10-06 23:13:52 +03:00
queries [ 1 ] . bindings . should . eql ( [
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
testUtils . filterData . data . posts [ 3 ] . id ,
2018-10-06 23:13:52 +03:00
'photo' ,
'video' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
false ,
'published' ,
2018-10-06 23:13:52 +03:00
3
] ) ;
} ) ;
} ) ;
it ( 'generates correct query for - filter: authors:[leslie,pat]+(tag:hash-audio,feature_image:-null), with related: authors,tags' , function ( ) {
const queries = [ ] ;
tracker . install ( ) ;
tracker . on ( 'query' , ( query ) => {
queries . push ( query ) ;
query . response ( [ ] ) ;
} ) ;
return models . Post . findPage ( {
filter : 'authors:[leslie,pat]+(tag:hash-audio,feature_image:-null)' ,
withRelated : [ 'authors' , 'tags' ]
} ) . then ( ( ) => {
queries . length . should . eql ( 2 ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 0 ] . sql . should . eql ( 'select count(distinct posts.id) as aggregate from `posts` where (((`posts`.`feature_image` is not null or `posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` where `tags`.`slug` = ?)) and `posts`.`id` in (select `posts_authors`.`post_id` from `posts_authors` inner join `users` as `authors` on `authors`.`id` = `posts_authors`.`author_id` where `authors`.`slug` in (?, ?))) and (`posts`.`page` = ? and `posts`.`status` = ?))' ) ;
2018-10-06 23:13:52 +03:00
queries [ 0 ] . bindings . should . eql ( [
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'hash-audio' ,
2018-10-06 23:13:52 +03:00
'leslie' ,
'pat' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
false ,
'published'
2018-10-06 23:13:52 +03:00
] ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 1 ] . sql . should . eql ( 'select `posts`.* from `posts` where (((`posts`.`feature_image` is not null or `posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` where `tags`.`slug` = ?)) and `posts`.`id` in (select `posts_authors`.`post_id` from `posts_authors` inner join `users` as `authors` on `authors`.`id` = `posts_authors`.`author_id` where `authors`.`slug` in (?, ?))) and (`posts`.`page` = ? and `posts`.`status` = ?)) order by (SELECT count(*) FROM posts_authors WHERE post_id = posts.id) DESC, CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?' ) ;
2018-10-06 23:13:52 +03:00
queries [ 1 ] . bindings . should . eql ( [
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'hash-audio' ,
2018-10-06 23:13:52 +03:00
'leslie' ,
'pat' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
false ,
'published' ,
2018-10-06 23:13:52 +03:00
15
] ) ;
} ) ;
} ) ;
it ( 'generates correct query for - filter: published_at:>\'2015-07-20\', limit of: 5, with related: tags' , function ( ) {
const queries = [ ] ;
tracker . install ( ) ;
tracker . on ( 'query' , ( query ) => {
queries . push ( query ) ;
query . response ( [ ] ) ;
} ) ;
return models . Post . findPage ( {
filter : 'published_at:>\'2015-07-20\'' ,
limit : 5 ,
withRelated : [ 'tags' ]
} ) . then ( ( ) => {
queries . length . should . eql ( 2 ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 0 ] . sql . should . eql ( 'select count(distinct posts.id) as aggregate from `posts` where (`posts`.`published_at` > ? and (`posts`.`page` = ? and `posts`.`status` = ?))' ) ;
2018-10-06 23:13:52 +03:00
queries [ 0 ] . bindings . should . eql ( [
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'2015-07-20' ,
2018-10-06 23:13:52 +03:00
false ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'published'
2018-10-06 23:13:52 +03:00
] ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 1 ] . sql . should . eql ( 'select `posts`.* from `posts` where (`posts`.`published_at` > ? and (`posts`.`page` = ? and `posts`.`status` = ?)) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?' ) ;
2018-10-06 23:13:52 +03:00
queries [ 1 ] . bindings . should . eql ( [
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'2015-07-20' ,
2018-10-06 23:13:52 +03:00
false ,
'published' ,
5
] ) ;
} ) ;
} ) ;
describe ( 'primary_tag/primary_author' , function ( ) {
it ( 'generates correct query for - filter: primary_tag:photo, with related: tags' , function ( ) {
const queries = [ ] ;
tracker . install ( ) ;
tracker . on ( 'query' , ( query ) => {
queries . push ( query ) ;
query . response ( [ ] ) ;
} ) ;
return models . Post . findPage ( {
filter : 'primary_tag:photo' ,
withRelated : [ 'tags' ]
} ) . then ( ( ) => {
queries . length . should . eql ( 2 ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 0 ] . sql . should . eql ( 'select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` and `posts_tags`.`sort_order` = 0 where `tags`.`slug` = ? and `tags`.`visibility` = ?)) and (`posts`.`page` = ? and `posts`.`status` = ?))' ) ;
2018-10-06 23:13:52 +03:00
queries [ 0 ] . bindings . should . eql ( [
'photo' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'public' ,
false ,
'published'
2018-10-06 23:13:52 +03:00
] ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 1 ] . sql . should . eql ( 'select `posts`.* from `posts` where ((`posts`.`id` in (select `posts_tags`.`post_id` from `posts_tags` inner join `tags` on `tags`.`id` = `posts_tags`.`tag_id` and `posts_tags`.`sort_order` = 0 where `tags`.`slug` = ? and `tags`.`visibility` = ?)) and (`posts`.`page` = ? and `posts`.`status` = ?)) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?' ) ;
2018-10-06 23:13:52 +03:00
queries [ 1 ] . bindings . should . eql ( [
'photo' ,
'public' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
false ,
'published' ,
2018-10-06 23:13:52 +03:00
15
] ) ;
} ) ;
} ) ;
it ( 'generates correct query for - filter: primary_author:leslie, with related: authors' , function ( ) {
const queries = [ ] ;
tracker . install ( ) ;
tracker . on ( 'query' , ( query ) => {
queries . push ( query ) ;
query . response ( [ ] ) ;
} ) ;
return models . Post . findPage ( {
filter : 'primary_author:leslie' ,
withRelated : [ 'authors' ]
} ) . then ( ( ) => {
queries . length . should . eql ( 2 ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 0 ] . sql . should . eql ( 'select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`id` in (select `posts_authors`.`post_id` from `posts_authors` inner join `users` as `authors` on `authors`.`id` = `posts_authors`.`author_id` and `posts_authors`.`sort_order` = 0 where `authors`.`slug` = ? and `authors`.`visibility` = ?)) and (`posts`.`page` = ? and `posts`.`status` = ?))' ) ;
2018-10-06 23:13:52 +03:00
queries [ 0 ] . bindings . should . eql ( [
'leslie' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'public' ,
false ,
'published'
2018-10-06 23:13:52 +03:00
] ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 1 ] . sql . should . eql ( 'select `posts`.* from `posts` where ((`posts`.`id` in (select `posts_authors`.`post_id` from `posts_authors` inner join `users` as `authors` on `authors`.`id` = `posts_authors`.`author_id` and `posts_authors`.`sort_order` = 0 where `authors`.`slug` = ? and `authors`.`visibility` = ?)) and (`posts`.`page` = ? and `posts`.`status` = ?)) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC limit ?' ) ;
2018-10-06 23:13:52 +03:00
queries [ 1 ] . bindings . should . eql ( [
'leslie' ,
'public' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
false ,
'published' ,
2018-10-06 23:13:52 +03:00
15
] ) ;
} ) ;
} ) ;
} ) ;
describe ( 'bad behavior' , function ( ) {
it ( 'generates correct query for - filter: status:[published,draft], limit of: all' , function ( ) {
const queries = [ ] ;
tracker . install ( ) ;
tracker . on ( 'query' , ( query ) => {
queries . push ( query ) ;
query . response ( [ ] ) ;
} ) ;
return models . Post . findPage ( {
filter : 'status:[published,draft]' ,
limit : 'all' ,
status : 'published' ,
where : {
statements : [ {
prop : 'status' ,
op : '=' ,
value : 'published'
} ]
}
} ) . then ( ( ) => {
queries . length . should . eql ( 2 ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 0 ] . sql . should . eql ( 'select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`status` in (?, ?) and `posts`.`status` = ?) and (`posts`.`page` = ?))' ) ;
2018-10-06 23:13:52 +03:00
queries [ 0 ] . bindings . should . eql ( [
'published' ,
'draft' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'published' ,
false ,
2018-10-06 23:13:52 +03:00
] ) ;
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
queries [ 1 ] . sql . should . eql ( 'select `posts`.* from `posts` where ((`posts`.`status` in (?, ?) and `posts`.`status` = ?) and (`posts`.`page` = ?)) order by CASE WHEN posts.status = \'scheduled\' THEN 1 WHEN posts.status = \'draft\' THEN 2 ELSE 3 END ASC,CASE WHEN posts.status != \'draft\' THEN posts.published_at END DESC,posts.updated_at DESC,posts.id DESC' ) ;
2018-10-06 23:13:52 +03:00
queries [ 1 ] . bindings . should . eql ( [
'published' ,
'draft' ,
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16
- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.
NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 13:53:40 +03:00
'published' ,
false ,
2018-10-06 23:13:52 +03:00
] ) ;
} ) ;
} ) ;
} ) ;
} ) ;
2018-02-07 12:46:22 +03:00
2018-10-09 16:31:09 +03:00
describe ( 'toJSON' , function ( ) {
const toJSON = function toJSON ( model , options ) {
return new models . Post ( model ) . toJSON ( options ) ;
} ;
2018-03-05 11:10:27 +03:00
2018-10-09 16:31:09 +03:00
it ( 'ensure mobiledoc revisions are never exposed' , function ( ) {
const post = {
mobiledoc : 'test' ,
mobiledoc _revisions : [ ] ,
} ;
2018-03-05 11:10:27 +03:00
2018-10-09 16:31:09 +03:00
const json = toJSON ( post , { formats : [ 'mobiledoc' ] } ) ;
2018-03-05 11:10:27 +03:00
2018-10-09 16:31:09 +03:00
should . not . exist ( json . mobiledoc _revisions ) ;
should . exist ( json . mobiledoc ) ;
} ) ;
2018-03-27 17:16:15 +03:00
} ) ;
2018-03-05 11:10:27 +03:00
2018-11-15 17:53:24 +03:00
describe ( 'extraFilters' , function ( ) {
2018-10-06 23:13:52 +03:00
it ( 'generates correct where statement when filter contains unpermitted values' , function ( ) {
const options = {
filter : 'status:[published,draft]' ,
limit : 'all' ,
status : 'published'
} ;
2018-11-15 17:53:24 +03:00
const filter = new models . Post ( ) . extraFilters ( options ) ;
filter . should . eql ( 'status:published' ) ;
2018-10-06 23:13:52 +03:00
} ) ;
} ) ;
describe ( 'enforcedFilters' , function ( ) {
const enforcedFilters = function enforcedFilters ( model , options ) {
return new models . Post ( model ) . enforcedFilters ( options ) ;
} ;
it ( 'returns published status filter for public context' , function ( ) {
const options = {
context : {
public : true
}
} ;
const filter = enforcedFilters ( { } , options ) ;
filter . should . equal ( 'status:published' ) ;
} ) ;
it ( 'returns no status filter for non public context' , function ( ) {
const options = {
context : {
internal : true
}
} ;
const filter = enforcedFilters ( { } , options ) ;
should ( filter ) . equal ( null ) ;
} ) ;
} ) ;
describe ( 'defaultFilters' , function ( ) {
const defaultFilters = function defaultFilters ( model , options ) {
return new models . Post ( model ) . defaultFilters ( options ) ;
} ;
it ( 'returns no default filter for internal context' , function ( ) {
const options = {
context : {
internal : true
}
} ;
const filter = defaultFilters ( { } , options ) ;
should ( filter ) . equal ( null ) ;
} ) ;
it ( 'returns page:false filter for public context' , function ( ) {
const options = {
context : {
public : true
}
} ;
const filter = defaultFilters ( { } , options ) ;
filter . should . equal ( 'page:false' ) ;
} ) ;
it ( 'returns page:false+status:published filter for non public context' , function ( ) {
const options = {
context : 'user'
} ;
const filter = defaultFilters ( { } , options ) ;
filter . should . equal ( 'page:false+status:published' ) ;
} ) ;
} ) ;
2018-10-09 16:31:09 +03:00
} ) ;
describe ( 'Unit: models/post: uses database (@TODO: fix me)' , function ( ) {
before ( function ( ) {
models . init ( ) ;
} ) ;
before ( testUtils . teardown ) ;
before ( testUtils . setup ( 'users:roles' , 'posts' ) ) ;
beforeEach ( function ( ) {
sandbox . stub ( security . password , 'hash' ) . resolves ( '$2a$10$we16f8rpbrFZ34xWj0/ZC.LTPUux8ler7bcdTs5qIleN6srRHhilG' ) ;
sandbox . stub ( urlService , 'getUrlByResourceId' ) ;
} ) ;
afterEach ( function ( ) {
sandbox . restore ( ) ;
} ) ;
after ( function ( ) {
sandbox . restore ( ) ;
} ) ;
2018-10-06 23:13:52 +03:00
2018-04-15 13:12:20 +03:00
describe ( 'add' , function ( ) {
describe ( 'ensure full set of data for model events' , function ( ) {
it ( 'default' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . add ( {
title : 'My beautiful title.' ,
tags : [ {
name : 'my-tag'
} ]
} , testUtils . context . editor )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( post . hasOwnProperty ( key ) ) ;
2018-06-26 17:00:54 +03:00
if ( [ 'page' , 'status' , 'visibility' , 'featured' ] . indexOf ( key ) !== - 1 ) {
events . post [ 0 ] . data [ key ] . should . eql ( schema . tables . posts [ key ] . defaultTo ) ;
}
2018-04-15 13:12:20 +03:00
} ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . primary _author ) ;
should . not . exist ( post . tags ) ;
should . not . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'added' ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( events . post [ 0 ] . data . hasOwnProperty ( key ) ) ;
2018-06-26 17:00:54 +03:00
if ( [ 'page' , 'status' , 'visibility' , 'featured' ] . indexOf ( key ) !== - 1 ) {
events . post [ 0 ] . data [ key ] . should . eql ( schema . tables . posts [ key ] . defaultTo ) ;
}
2018-04-15 13:12:20 +03:00
} ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
2018-06-26 17:00:54 +03:00
it ( 'with page:1' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . add ( {
title : 'My beautiful title.' ,
page : 1
} , testUtils . context . editor )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
// transformed 1 to true
post . page . should . eql ( true ) ;
events . post [ 0 ] . data . page . should . eql ( true ) ;
} ) ;
} ) ;
2018-04-15 13:12:20 +03:00
it ( 'use `withRelated=tags`' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . add ( {
title : 'My beautiful title.' ,
tags : [ {
name : 'my-tag'
} ]
} , _ . merge ( {
withRelated : [ 'tags' ]
} , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . primary _author ) ;
should . exist ( post . tags ) ;
should . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'added' ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
it ( 'use `withRelated=tags,authors`' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . add ( {
title : 'My beautiful title.' ,
tags : [ {
name : 'my-tag'
} ]
} , _ . merge ( {
withRelated : [ 'tags' , 'authors' ]
} , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
should . exist ( post . authors ) ;
should . exist ( post . primary _author ) ;
should . exist ( post . tags ) ;
should . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'added' ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
it ( 'use `columns=title`' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . add ( {
title : 'My beautiful title.' ,
tags : [ {
name : 'my-tag'
} ]
} , _ . merge ( {
columns : [ 'title' ]
} , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'title' , 'id' ] ) ) , ( key ) => {
should . not . exist ( post [ key ] ) ;
} ) ;
should . exist ( post . id ) ;
should . exist ( post . title ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . primary _author ) ;
should . not . exist ( post . tags ) ;
should . not . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'added' ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( events . post [ 0 ] . data . hasOwnProperty ( key ) ) ;
} ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
it ( 'use `formats=mobiledoc`' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . add ( {
title : 'My beautiful title.' ,
tags : [ {
name : 'my-tag'
} ]
} , _ . merge ( {
formats : [ 'mobiledoc' ]
} , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'html' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( post . hasOwnProperty ( key ) ) ;
} ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . primary _author ) ;
should . not . exist ( post . tags ) ;
should . not . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'added' ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( events . post [ 0 ] . data . hasOwnProperty ( key ) ) ;
} ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
} ) ;
} ) ;
describe ( 'edit' , function ( ) {
2018-10-06 23:13:52 +03:00
it ( 'ensure `forUpdate` works' , function ( done ) {
const originalFn = models . Post . prototype . onSaving ;
let requestCanComeIn = false ;
let postId = testUtils . DataGenerator . forKnex . posts [ 4 ] . id ;
testUtils . DataGenerator . forKnex . posts [ 4 ] . featured . should . eql ( true ) ;
// @NOTE: simulate that the onSaving hook takes longer
sandbox . stub ( models . Post . prototype , 'onSaving' ) . callsFake ( function ( ) {
var self = this ,
args = arguments ;
models . Post . prototype . onSaving . restore ( ) ;
requestCanComeIn = true ;
return Promise . delay ( 2000 )
. then ( function ( ) {
return originalFn . apply ( self , args ) ;
} ) ;
} ) ;
const interval = setInterval ( function ( ) {
if ( requestCanComeIn ) {
clearInterval ( interval ) ;
// @NOTE: second call, should wait till the delay finished
models . Post . edit ( { title : 'Berlin' } , { id : postId , context : { internal : true } } )
. then ( function ( post ) {
post . id . should . eql ( postId ) ;
post . get ( 'title' ) . should . eql ( 'Berlin' ) ;
post . get ( 'status' ) . should . eql ( 'published' ) ;
post . get ( 'featured' ) . should . be . false ( ) ;
done ( ) ;
} )
. catch ( done ) ;
}
} , 10 ) ;
// @NOTE: first call to db locks the row (!)
models . Post . edit ( { title : 'First' , featured : false , status : 'published' } , _ . merge ( { id : postId , migrating : true } , testUtils . context . editor ) ) ;
} ) ;
2018-08-22 14:57:12 +03:00
it ( 'update post with options.migrating' , function ( ) {
const events = {
post : [ ] ,
tag : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( event ) ;
} ) ;
sandbox . stub ( models . Tag . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . tag . push ( event ) ;
} ) ;
let originalUpdatedAt ;
let originalUpdatedBy ;
return models . Post . findOne ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
status : 'draft'
} , { withRelated : [ 'tags' ] } )
. then ( ( post ) => {
originalUpdatedAt = post . get ( 'updated_at' ) ;
originalUpdatedBy = post . get ( 'updated_by' ) ;
// post will be updated, tags relation not
return models . Post . edit ( {
html : 'changed html'
} , _ . merge ( { id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id , migrating : true } , testUtils . context . editor ) ) ;
} )
. then ( ( post ) => {
post . get ( 'updated_at' ) . should . eql ( originalUpdatedAt ) ;
post . get ( 'updated_by' ) . should . eql ( originalUpdatedBy ) ;
events . post . should . eql ( [ 'edited' ] ) ;
events . tag . should . eql ( [ ] ) ;
} ) ;
} ) ;
2018-04-05 18:34:09 +03:00
it ( 'update post, relation has not changed' , function ( ) {
const events = {
post : [ ] ,
tag : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( event ) ;
} ) ;
sandbox . stub ( models . Tag . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . tag . push ( event ) ;
} ) ;
2018-04-16 01:29:17 +03:00
return models . Post . findOne ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
status : 'draft'
} , { withRelated : [ 'tags' ] } )
2018-04-05 18:34:09 +03:00
. then ( ( post ) => {
// post will be updated, tags relation not
return models . Post . edit ( {
title : 'change' ,
2018-06-12 21:26:16 +03:00
tags : post . related ( 'tags' ) . attributes
2018-04-05 18:34:09 +03:00
} , _ . merge ( { id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id } , testUtils . context . editor ) ) ;
} )
. then ( ( post ) => {
post . updated ( 'title' ) . should . eql ( testUtils . DataGenerator . forKnex . posts [ 3 ] . title ) ;
post . get ( 'title' ) . should . eql ( 'change' ) ;
events . post . should . eql ( [ 'edited' ] ) ;
events . tag . should . eql ( [ ] ) ;
} ) ;
} ) ;
it ( 'update post, relation has changed' , function ( ) {
const events = {
post : [ ] ,
tag : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( event ) ;
} ) ;
sandbox . stub ( models . Tag . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . tag . push ( event ) ;
} ) ;
2018-04-16 01:29:17 +03:00
return models . Post . findOne ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
status : 'draft'
} , { withRelated : [ 'tags' ] } )
2018-04-05 18:34:09 +03:00
. then ( ( post ) => {
// post will be updated, tags relation not
return models . Post . edit ( {
title : 'change' ,
tags : [ { id : post . related ( 'tags' ) . toJSON ( ) [ 0 ] . id , slug : 'after' } ]
} , _ . merge ( { id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id } , testUtils . context . editor ) ) ;
} )
. then ( ( post ) => {
post . updated ( 'title' ) . should . eql ( 'change' ) ;
post . get ( 'title' ) . should . eql ( 'change' ) ;
events . post . should . eql ( [ 'edited' ] ) ;
events . tag . should . eql ( [ 'edited' ] ) ;
} ) ;
} ) ;
2018-03-05 11:10:27 +03:00
it ( 'resets given empty value to null' , function ( ) {
return models . Post . findOne ( { slug : 'html-ipsum' } )
. then ( function ( post ) {
post . get ( 'slug' ) . should . eql ( 'html-ipsum' ) ;
post . get ( 'feature_image' ) . should . eql ( 'https://example.com/super_photo.jpg' ) ;
post . set ( 'feature_image' , '' ) ;
post . set ( 'custom_excerpt' , '' ) ;
return post . save ( ) ;
} )
. then ( function ( post ) {
should ( post . get ( 'feature_image' ) ) . be . null ( ) ;
post . get ( 'custom_excerpt' ) . should . eql ( '' ) ;
} ) ;
} ) ;
2018-04-15 13:12:20 +03:00
describe ( 'ensure full set of data for model events' , function ( ) {
it ( 'default' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . edit ( {
title : 'My beautiful title.'
} , _ . merge ( { id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id } , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( post . hasOwnProperty ( key ) ) ;
} ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . primary _author ) ;
should . not . exist ( post . tags ) ;
should . not . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'edited' ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( events . post [ 0 ] . data . hasOwnProperty ( key ) ) ;
} ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
it ( 'use `withRelated=tags`' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . edit ( {
title : 'My beautiful title.'
} , _ . merge ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'tags' ]
} , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( post . hasOwnProperty ( key ) ) ;
} ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . primary _author ) ;
should . exist ( post . tags ) ;
should . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'edited' ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( events . post [ 0 ] . data . hasOwnProperty ( key ) ) ;
} ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
it ( 'use `withRelated=tags,authors`' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . edit ( {
title : 'My beautiful title.'
} , _ . merge ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'tags' , 'authors' ]
} , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( post . hasOwnProperty ( key ) ) ;
} ) ;
should . exist ( post . authors ) ;
should . exist ( post . primary _author ) ;
should . exist ( post . tags ) ;
should . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'edited' ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( events . post [ 0 ] . data . hasOwnProperty ( key ) ) ;
} ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
it ( 'use `columns=title`' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . edit ( {
title : 'My beautiful title.'
} , _ . merge ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
columns : [ 'title' ]
} , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'title' , 'id' ] ) ) , ( key ) => {
should . not . exist ( post [ key ] ) ;
} ) ;
should . exist ( post . id ) ;
should . exist ( post . title ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . primary _author ) ;
should . not . exist ( post . tags ) ;
should . not . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'edited' ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( events . post [ 0 ] . data . hasOwnProperty ( key ) ) ;
} ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
it ( 'use `formats=mobiledoc`' , function ( ) {
const events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
return models . Post . edit ( {
title : 'My beautiful title.'
} , _ . merge ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
formats : [ 'mobiledoc' ]
} , testUtils . context . editor ) )
. then ( ( post ) => {
post . get ( 'title' ) . should . eql ( 'My beautiful title.' ) ;
post = post . toJSON ( ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'html' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( post . hasOwnProperty ( key ) ) ;
} ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . primary _author ) ;
should . not . exist ( post . tags ) ;
should . not . exist ( post . primary _tag ) ;
events . post [ 0 ] . event . should . eql ( 'edited' ) ;
_ . each ( _ . keys ( _ . omit ( schema . tables . posts , [ 'mobiledoc' , 'amp' , 'plaintext' ] ) ) , ( key ) => {
should . exist ( events . post [ 0 ] . data . hasOwnProperty ( key ) ) ;
} ) ;
should . exist ( events . post [ 0 ] . data . authors ) ;
should . exist ( events . post [ 0 ] . data . primary _author ) ;
should . exist ( events . post [ 0 ] . data . tags ) ;
should . exist ( events . post [ 0 ] . data . primary _tag ) ;
} ) ;
} ) ;
} ) ;
2018-03-05 11:10:27 +03:00
} ) ;
2018-03-27 17:16:15 +03:00
describe ( 'Relations' , function ( ) {
describe ( 'author/authors' , function ( ) {
describe ( 'add' , function ( ) {
it ( 'with invalid post.author_id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
post . author _id = '12345' ;
return models . Post . add ( post , {
context : { user : testUtils . DataGenerator . forKnex . users [ 2 ] . id } ,
withRelated : [ 'author' , 'authors' ]
} ) . then ( function ( ) {
'Expected error' . should . eql ( false ) ;
} ) . catch ( function ( err ) {
( err instanceof common . errors . ValidationError ) . should . eql ( true ) ;
} ) ;
} ) ;
it ( 'with invalid post.authors[0].id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
delete post . author _id ;
delete post . author ;
post . authors = [ {
id : '12345'
} ] ;
return models . Post . add ( post , {
context : { user : testUtils . DataGenerator . forKnex . users [ 2 ] . id } ,
withRelated : [ 'author' , 'authors' ]
} ) . then ( function ( ) {
'Expected error' . should . eql ( false ) ;
} ) . catch ( function ( err ) {
( err instanceof common . errors . ValidationError ) . should . eql ( true ) ;
} ) ;
} ) ;
// NOTE: this can be supported as soon as we remove the deprecation for post.author_id
it ( '[unsupported] insert post.authors[0]' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
delete post . author _id ;
delete post . author ;
post . authors = [ {
name : 'Gregor'
} ] ;
return models . Post . add ( post , {
context : { user : testUtils . DataGenerator . forKnex . users [ 2 ] . id } ,
withRelated : [ 'author' , 'authors' ]
} ) . then ( function ( ) {
'Expected error' . should . eql ( false ) ;
} ) . catch ( function ( err ) {
( err [ 0 ] instanceof common . errors . ValidationError ) . should . eql ( true ) ;
} ) ;
} ) ;
it ( 'with invalid post.author_id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
post . author _id = '12345' ;
return models . Post . add ( post , {
context : { user : testUtils . DataGenerator . forKnex . users [ 2 ] . id } ,
withRelated : [ 'author' , 'authors' ]
} ) . then ( function ( ) {
'Expected error' . should . eql ( false ) ;
} ) . catch ( function ( err ) {
( err instanceof common . errors . ValidationError ) . should . eql ( true ) ;
} ) ;
} ) ;
it ( 'without author_id/author/authors' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
delete post . author _id ;
delete post . author ;
delete post . authors ;
return models . Post . add ( post , {
context : { user : testUtils . DataGenerator . forKnex . users [ 2 ] . id } ,
withRelated : [ 'author' , 'authors' ]
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
post . authors . length . should . eql ( 1 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
} ) ;
it ( 'without author/authors' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
post . author _id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
return models . Post . add ( post , { withRelated : [ 'author' , 'authors' ] } )
. then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors . length . should . eql ( 1 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
} ) ;
} ) ;
it ( 'without author/authors' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
post . author _id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
return models . Post . add ( post , { withRelated : [ 'author' ] } )
. then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
should . not . exist ( post . authors ) ;
} ) ;
} ) ;
it ( 'with author, with author_id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
post . author _id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . author = {
id : testUtils . DataGenerator . forKnex . users [ 1 ] . id
} ;
return models . Post . add ( post , { withRelated : [ 'author' ] } )
. then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
should . not . exist ( post . authors ) ;
} ) ;
} ) ;
it ( '[unsupported] with author, without author_id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
delete post . author _id ;
post . author = {
id : testUtils . DataGenerator . forKnex . users [ 2 ] . id
} ;
return models . Post . add ( post , {
withRelated : [ 'author' ] ,
context : { user : testUtils . DataGenerator . forKnex . users [ 0 ] . id }
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
// no update happened, because `post.author` is ignored
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
should . not . exist ( post . authors ) ;
} ) ;
} ) ;
2018-04-10 01:20:19 +03:00
it ( '[not allowed] with empty authors ([]), without author_id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
delete post . author _id ;
post . authors = [ ] ;
return models . Post . add ( post , { withRelated : [ 'author' , 'authors' ] } )
. then ( function ( ) {
'Expected error' . should . eql ( false ) ;
} )
. catch ( function ( err ) {
( err instanceof common . errors . ValidationError ) . should . eql ( true ) ;
} ) ;
} ) ;
it ( '[not allowed] with empty authors ([]), with author_id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
post . author _id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors = [ ] ;
return models . Post . add ( post , { withRelated : [ 'author' , 'authors' ] } )
. then ( function ( ) {
'Expected error' . should . eql ( false ) ;
} )
. catch ( function ( err ) {
( err instanceof common . errors . ValidationError ) . should . eql ( true ) ;
} ) ;
} ) ;
2018-03-27 17:16:15 +03:00
it ( 'with authors, with author_id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
post . author _id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors = [ {
id : testUtils . DataGenerator . forKnex . users [ 0 ] . id
} ] ;
return models . Post . add ( post , { withRelated : [ 'author' , 'authors' ] } )
. then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors . length . should . eql ( 1 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
} ) ;
} ) ;
it ( 'with authors, without author_id' , function ( ) {
const post = testUtils . DataGenerator . forKnex . createPost ( ) ;
delete post . author _id ;
post . authors = [ {
id : testUtils . DataGenerator . forKnex . users [ 0 ] . id
} ] ;
return models . Post . add ( post , {
context : { user : testUtils . DataGenerator . forKnex . users [ 0 ] . id } ,
withRelated : [ 'author' , 'authors' ]
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors . length . should . eql ( 1 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
} ) ;
} ) ;
} ) ;
describe ( 'findOne' , function ( ) {
it ( 'withRelated: []' , function ( ) {
2018-04-16 01:29:17 +03:00
return models . Post . findOne ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
status : 'draft'
} , { withRelated : [ ] } )
2018-03-27 17:16:15 +03:00
. then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
should . not . exist ( post . authors ) ;
should . not . exist ( post . author _id ) ;
} ) ;
} ) ;
it ( 'withRelated: [author]' , function ( ) {
2018-04-16 01:29:17 +03:00
return models . Post . findOne ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
status : 'draft'
} , { withRelated : [ 'author' ] } )
2018-03-27 17:16:15 +03:00
. then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
should . not . exist ( post . authors ) ;
} ) ;
} ) ;
it ( 'withRelated: [authors]' , function ( ) {
2018-04-16 01:29:17 +03:00
return models . Post . findOne ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
status : 'draft'
} , { withRelated : [ 'authors' ] } )
2018-03-27 17:16:15 +03:00
. then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors . length . should . eql ( 2 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors [ 1 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
} ) ;
it ( 'withRelated: [authors, author]' , function ( ) {
2018-04-16 01:29:17 +03:00
return models . Post . findOne ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
status : 'draft'
} , { withRelated : [ 'authors' , 'author' ] } )
2018-03-27 17:16:15 +03:00
. then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors . length . should . eql ( 2 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors [ 1 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
} ) ;
} ) ;
describe ( 'edit' , function ( ) {
2018-06-12 21:26:16 +03:00
beforeEach ( testUtils . teardown ) ;
beforeEach ( testUtils . setup ( 'users:roles' , 'posts' ) ) ;
2018-03-27 17:16:15 +03:00
2018-06-12 21:26:16 +03:00
beforeEach ( function ( ) {
2018-03-27 17:16:15 +03:00
// posts[3] has the following author_id
testUtils . DataGenerator . forKnex . posts [ 3 ] . author _id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
// posts[3] has two authors relations
testUtils . DataGenerator . forKnex . posts _authors [ 3 ] . post _id . should . eql ( testUtils . DataGenerator . forKnex . posts [ 3 ] . id ) ;
testUtils . DataGenerator . forKnex . posts _authors [ 3 ] . author _id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
testUtils . DataGenerator . forKnex . posts _authors [ 4 ] . post _id . should . eql ( testUtils . DataGenerator . forKnex . posts [ 3 ] . id ) ;
testUtils . DataGenerator . forKnex . posts _authors [ 4 ] . author _id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
it ( '[not allowed] post.authors = []' , function ( ) {
const data = {
authors : [ ]
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' , 'author' ]
} ) . then ( function ( ) {
'Expected Error' . should . eql ( true ) ;
} ) . catch ( function ( err ) {
( err instanceof common . errors . ValidationError ) . should . be . true ;
} ) ;
} ) ;
it ( '[not allowed] primary authors are not equal' , function ( ) {
const data = {
author _id : testUtils . DataGenerator . forKnex . users [ 2 ] . id ,
authors : [ {
id : testUtils . DataGenerator . forKnex . users [ 1 ] . id
} ]
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' , 'author' ]
} ) . then ( function ( ) {
'Expected Error' . should . eql ( true ) ;
} ) . catch ( function ( err ) {
( err instanceof common . errors . ValidationError ) . should . be . true ;
} ) ;
} ) ;
it ( '[not allowed] primary authors are not equal' , function ( ) {
const data = {
author : {
id : testUtils . DataGenerator . forKnex . users [ 2 ] . id
} ,
authors : [ {
id : testUtils . DataGenerator . forKnex . users [ 1 ] . id
} ]
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' , 'author' ]
} ) . then ( function ( ) {
'Expected Error' . should . eql ( true ) ;
} ) . catch ( function ( err ) {
( err instanceof common . errors . ValidationError ) . should . be . true ;
} ) ;
} ) ;
it ( 'change post.author_id [has existing post.authors]' , function ( ) {
const data = {
author _id : testUtils . DataGenerator . forKnex . users [ 1 ] . id
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' , 'author' ]
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 1 ] . id ) ;
post . authors . length . should . eql ( 2 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 1 ] . id ) ;
post . authors [ 1 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
} ) ;
it ( 'change post.author_id [has existing post.authors] [without `withRelated`]' , function ( ) {
const data = {
author _id : testUtils . DataGenerator . forKnex . users [ 1 ] . id
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . should . eql ( testUtils . DataGenerator . forKnex . users [ 1 ] . id ) ;
should . not . exist ( post . authors ) ;
2018-04-16 01:29:17 +03:00
return models . Post . findOne ( {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
status : 'draft'
} , { withRelated : [ 'authors' ] } ) ;
2018-03-27 17:16:15 +03:00
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . authors . length . should . eql ( 2 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 1 ] . id ) ;
post . authors [ 1 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
} ) ;
it ( 'change post.authors' , function ( ) {
testUtils . DataGenerator . forKnex . posts [ 3 ] . author _id . should . not . equal ( testUtils . DataGenerator . forKnex . users [ 3 ] . id ) ;
const data = {
authors : [
{
id : testUtils . DataGenerator . forKnex . users [ 3 ] . id
} ,
{
id : testUtils . DataGenerator . forKnex . users [ 2 ] . id
}
]
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' , 'author' ]
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 3 ] . id ) ;
post . authors . length . should . eql ( 2 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 3 ] . id ) ;
post . authors [ 1 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
} ) ;
it ( 'change post.authors, do not include `author`' , function ( ) {
testUtils . DataGenerator . forKnex . posts [ 3 ] . author _id . should . not . equal ( testUtils . DataGenerator . forKnex . users [ 3 ] . id ) ;
const data = {
authors : [
{
id : testUtils . DataGenerator . forKnex . users [ 3 ] . id
} ,
{
id : testUtils . DataGenerator . forKnex . users [ 2 ] . id
}
]
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' ]
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . should . eql ( testUtils . DataGenerator . forKnex . users [ 3 ] . id ) ;
post . authors . length . should . eql ( 2 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 3 ] . id ) ;
post . authors [ 1 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
} ) ;
it ( 'change post.authors and post.author_id (different primary author)' , function ( ) {
const data = {
authors : [
{
id : testUtils . DataGenerator . forKnex . users [ 1 ] . id
}
] ,
author _id : testUtils . DataGenerator . forKnex . users [ 4 ] . id
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' , 'author' ]
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 1 ] . id ) ;
post . authors . length . should . eql ( 1 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 1 ] . id ) ;
} ) ;
} ) ;
it ( 'change order of existing post.authors' , function ( ) {
const data = {
authors : [
{
id : testUtils . DataGenerator . forKnex . users [ 2 ] . id
} ,
{
id : testUtils . DataGenerator . forKnex . users [ 0 ] . id
}
]
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' , 'author' ]
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
post . authors . length . should . eql ( 2 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
post . authors [ 1 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
} ) ;
} ) ;
it ( '[unsupported] change post.author' , function ( ) {
const data = {
author : {
id : testUtils . DataGenerator . forKnex . users [ 4 ] . id
}
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 3 ] . id ,
withRelated : [ 'authors' , 'author' ]
} ) . then ( function ( post ) {
post = post . toJSON ( ) ;
post . author . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors . length . should . eql ( 2 ) ;
post . authors [ 0 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 0 ] . id ) ;
post . authors [ 1 ] . id . should . eql ( testUtils . DataGenerator . forKnex . users [ 2 ] . id ) ;
} ) ;
} ) ;
2018-04-10 23:45:31 +03:00
it ( '[unsupported] change post.plaintext' , function ( ) {
const data = {
plaintext : 'test'
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 2 ] . id
} ) . then ( function ( post ) {
post = post . toJSON ( { formats : [ 'mobiledoc' , 'plaintext' , 'html' ] } ) ;
post . plaintext . should . eql ( testUtils . DataGenerator . forKnex . posts [ 2 ] . plaintext ) ;
} ) ;
} ) ;
it ( '[unsupported] change post.html' , function ( ) {
const data = {
html : 'test'
} ;
return models . Post . edit ( data , {
id : testUtils . DataGenerator . forKnex . posts [ 2 ] . id
} ) . then ( function ( post ) {
post = post . toJSON ( { formats : [ 'mobiledoc' , 'plaintext' , 'html' ] } ) ;
post . html . should . eql ( testUtils . DataGenerator . forKnex . posts [ 2 ] . html ) ;
} ) ;
} ) ;
2018-03-27 17:16:15 +03:00
} ) ;
describe ( 'destroy' , function ( ) {
it ( 'by author' , function ( ) {
const authorId = testUtils . DataGenerator . forKnex . users [ 0 ] . id ;
return knex ( 'posts_authors' )
. where ( 'author_id' , authorId )
. then ( function ( postAuthors ) {
postAuthors . length . should . eql ( 8 ) ;
return models . Post . destroyByAuthor ( { id : authorId } ) ;
} )
. then ( function ( ) {
return knex ( 'posts_authors' )
. where ( 'author_id' , authorId ) ;
} )
. then ( function ( postAuthors ) {
postAuthors . length . should . eql ( 0 ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
2018-02-07 12:46:22 +03:00
describe ( 'Permissible' , function ( ) {
describe ( 'As Contributor' , function ( ) {
describe ( 'Editing' , function ( ) {
it ( 'rejects if changing status' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'published' } ;
mockPostObj . get . withArgs ( 'status' ) . returns ( 'draft' ) ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
false
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . called ) . be . false ( ) ;
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if changing author id' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , author _id : 2 } ;
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 1 ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . calledOnce ) . be . true ( ) ;
should ( mockPostObj . related . called ) . be . false ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if changing authors.0' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , authors : [ { id : 2 } ] } ;
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
testUtils . permissions . contributor ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
should ( mockPostObj . related . calledTwice ) . be . false ( ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
2018-03-27 17:16:15 +03:00
it ( 'ignores if changes authors.1' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , authors : [ { id : 1 } , { id : 2 } ] } ;
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
mockPostObj . get . withArgs ( 'status' ) . returns ( 'draft' ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
testUtils . permissions . contributor ,
false ,
true
) . then ( ( result ) => {
should . exist ( result ) ;
should ( result . excludedAttrs ) . deepEqual ( [ 'authors' , 'tags' ] ) ;
should ( mockPostObj . get . callCount ) . eql ( 2 ) ;
should ( mockPostObj . related . callCount ) . eql ( 2 ) ;
done ( ) ;
} ) . catch ( done ) ;
} ) ;
2018-02-07 12:46:22 +03:00
it ( 'rejects if post is not draft' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'published' , author _id : 1 } ;
mockPostObj . get . withArgs ( 'status' ) . returns ( 'published' ) ;
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 1 ) ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . callCount ) . eql ( 3 ) ;
should ( mockPostObj . related . callCount ) . eql ( 1 ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if contributor is not author of post' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , author _id : 2 } ;
mockPostObj . get . withArgs ( 'status' ) . returns ( 'draft' ) ;
2018-03-27 17:16:15 +03:00
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 1 ) ;
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . callCount ) . eql ( 1 ) ;
should ( mockPostObj . related . callCount ) . eql ( 0 ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
it ( 'resolves if none of the above cases are true' , function ( ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , author _id : 1 } ;
mockPostObj . get . withArgs ( 'status' ) . returns ( 'draft' ) ;
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 1 ) ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
return models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( result ) => {
should . exist ( result ) ;
2018-03-27 17:16:15 +03:00
should ( result . excludedAttrs ) . deepEqual ( [ 'authors' , 'tags' ] ) ;
should ( mockPostObj . get . callCount ) . eql ( 3 ) ;
should ( mockPostObj . related . callCount ) . eql ( 1 ) ;
2018-02-07 12:46:22 +03:00
} ) ;
} ) ;
} ) ;
describe ( 'Adding' , function ( ) {
it ( 'rejects if "published" status' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'published' , author _id : 1 } ;
models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if different author id' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , author _id : 2 } ;
models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
done ( ) ;
} ) ;
} ) ;
2018-03-27 17:16:15 +03:00
it ( 'rejects if different logged in user and `authors.0`' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , authors : [ { id : 2 } ] } ;
models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
testUtils . permissions . contributor ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if same logged in user and `authors.0`, but different author_id' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , author _id : 3 , authors : [ { id : 1 } ] } ;
models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
testUtils . permissions . contributor ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if different logged in user and `authors.0`, but correct author_id' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , author _id : 1 , authors : [ { id : 2 } ] } ;
models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
testUtils . permissions . contributor ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'resolves if same logged in user and `authors.0`' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , authors : [ { id : 1 } ] } ;
models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
testUtils . permissions . contributor ,
false ,
true
) . then ( ( result ) => {
should . exist ( result ) ;
should ( result . excludedAttrs ) . deepEqual ( [ 'authors' , 'tags' ] ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
done ( ) ;
} ) . catch ( done ) ;
} ) ;
2018-02-07 12:46:22 +03:00
it ( 'resolves if none of the above cases are true' , function ( ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { status : 'draft' , author _id : 1 } ;
return models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( result ) => {
should . exist ( result ) ;
2018-03-27 17:16:15 +03:00
should ( result . excludedAttrs ) . deepEqual ( [ 'authors' , 'tags' ] ) ;
2018-02-07 12:46:22 +03:00
should ( mockPostObj . get . called ) . be . false ( ) ;
} ) ;
} ) ;
} ) ;
describe ( 'Destroying' , function ( ) {
it ( 'rejects if destroying another author\'s post' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
models . Post . permissible (
mockPostObj ,
'destroy' ,
context ,
{ } ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . calledOnce ) . be . true ( ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if destroying a published post' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
mockPostObj . get . withArgs ( 'status' ) . returns ( 'published' ) ;
models . Post . permissible (
mockPostObj ,
'destroy' ,
context ,
{ } ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . calledOnce ) . be . true ( ) ;
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
it ( 'resolves if none of the above cases are true' , function ( ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ;
mockPostObj . get . withArgs ( 'status' ) . returns ( 'draft' ) ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
return models . Post . permissible (
mockPostObj ,
'destroy' ,
context ,
{ } ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . contributor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( result ) => {
should . exist ( result ) ;
2018-03-27 17:16:15 +03:00
should ( result . excludedAttrs ) . deepEqual ( [ 'authors' , 'tags' ] ) ;
should ( mockPostObj . get . calledOnce ) . be . true ( ) ;
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
2018-02-07 12:46:22 +03:00
} ) ;
} ) ;
} ) ;
} ) ;
describe ( 'As Author' , function ( ) {
describe ( 'Editing' , function ( ) {
it ( 'rejects if editing another\'s post' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { author _id : 2 } ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 2 } ] } ) ;
2018-02-07 12:46:22 +03:00
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 2 ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . author ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . called ) . be . false ( ) ;
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if editing another\'s post (using `authors`)' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { authors : [ { id : 2 } ] } ;
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
testUtils . permissions . author ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
should ( mockPostObj . related . calledTwice ) . be . true ( ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if changing author' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { author _id : 2 } ;
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 1 ) ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
testUtils . permissions . author ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . calledOnce ) . be . true ( ) ;
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if changing authors' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { authors : [ { id : 2 } ] } ;
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
testUtils . permissions . author ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
should ( mockPostObj . related . calledTwice ) . be . true ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if changing authors and author_id' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { authors : [ { id : 1 } ] , author _id : 2 } ;
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 1 ) ;
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . author ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . calledOnce ) . be . true ( ) ;
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'rejects if changing authors and author_id' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { authors : [ { id : 2 } ] , author _id : 1 } ;
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 1 ) ;
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
testUtils . permissions . author ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
mockPostObj . get . callCount . should . eql ( 1 ) ;
mockPostObj . related . callCount . should . eql ( 2 ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
it ( 'resolves if none of the above cases are true' , function ( ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { author _id : 1 } ;
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 1 ) ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
2018-02-07 12:46:22 +03:00
return models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . author ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . calledOnce ) . be . true ( ) ;
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
2018-02-07 12:46:22 +03:00
} ) ;
} ) ;
} ) ;
describe ( 'Adding' , function ( ) {
it ( 'rejects if different author id' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { author _id : 2 } ;
models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . author ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
done ( ) ;
} ) ;
} ) ;
2018-03-27 17:16:15 +03:00
it ( 'rejects if different authors' , function ( done ) {
var mockPostObj = {
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { authors : [ { id : 2 } ] } ;
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 1 } ] } ) ;
models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
testUtils . permissions . author ,
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
should ( mockPostObj . get . called ) . be . false ( ) ;
done ( ) ;
} ) ;
} ) ;
2018-02-07 12:46:22 +03:00
it ( 'resolves if none of the above cases are true' , function ( ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { author _id : 1 } ;
return models . Post . permissible (
mockPostObj ,
'add' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . author ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
should ( mockPostObj . get . called ) . be . false ( ) ;
} ) ;
} ) ;
} ) ;
} ) ;
describe ( 'Everyone Else' , function ( ) {
it ( 'rejects if hasUserPermissions is false and not current owner' , function ( done ) {
var mockPostObj = {
2018-03-27 17:16:15 +03:00
get : sandbox . stub ( ) ,
related : sandbox . stub ( )
2018-02-07 12:46:22 +03:00
} ,
context = { user : 1 } ,
unsafeAttrs = { author _id : 2 } ;
2018-03-27 17:16:15 +03:00
mockPostObj . related . withArgs ( 'authors' ) . returns ( { models : [ { id : 2 } ] } ) ;
2018-02-07 12:46:22 +03:00
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 2 ) ;
models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . editor ,
2018-02-07 12:46:22 +03:00
false ,
true
) . then ( ( ) => {
done ( new Error ( 'Permissible function should have rejected.' ) ) ;
} ) . catch ( ( error ) => {
error . should . be . an . instanceof ( common . errors . NoPermissionError ) ;
2018-03-27 17:16:15 +03:00
should ( mockPostObj . get . called ) . be . false ( ) ;
should ( mockPostObj . related . calledOnce ) . be . true ( ) ;
2018-02-07 12:46:22 +03:00
done ( ) ;
} ) ;
} ) ;
it ( 'resolves if hasUserPermission is true' , function ( ) {
var mockPostObj = {
get : sandbox . stub ( )
} ,
context = { user : 1 } ,
unsafeAttrs = { author _id : 2 } ;
mockPostObj . get . withArgs ( 'author_id' ) . returns ( 2 ) ;
return models . Post . permissible (
mockPostObj ,
'edit' ,
context ,
unsafeAttrs ,
2018-03-05 11:10:27 +03:00
testUtils . permissions . editor ,
2018-02-07 12:46:22 +03:00
true ,
true
) . then ( ( ) => {
should ( mockPostObj . get . called ) . be . false ( ) ;
} ) ;
} ) ;
} ) ;
} ) ;
2018-05-04 16:59:39 +03:00
describe ( 'Mobiledoc conversion' , function ( ) {
let labs = require ( '../../../server/services/labs' ) ;
let origLabs = _ . cloneDeep ( labs ) ;
let events ;
beforeEach ( function ( ) {
events = {
post : [ ]
} ;
sandbox . stub ( models . Post . prototype , 'emitChange' ) . callsFake ( function ( event ) {
events . post . push ( { event : event , data : this . toJSON ( ) } ) ;
} ) ;
} ) ;
2018-08-03 14:02:14 +03:00
it ( 'converts correctly' , function ( ) {
2018-05-04 16:59:39 +03:00
let newPost = testUtils . DataGenerator . forModel . posts [ 2 ] ;
return models . Post . add (
newPost ,
testUtils . context . editor
) . then ( ( post ) => {
should . exist ( post ) ;
post . has ( 'html' ) . should . equal ( true ) ;
2018-07-23 14:23:02 +03:00
post . get ( 'html' ) . should . equal ( '<h2 id="testing">testing</h2>\n<p>mctesters</p>\n<ul>\n<li>test</li>\n<li>line</li>\n<li>items</li>\n</ul>\n' ) ;
2018-05-04 16:59:39 +03:00
} ) ;
} ) ;
} ) ;
2018-02-07 12:46:22 +03:00
} ) ;