🏗 Migrated posts.page column to posts.type (#11111)

refs https://github.com/TryGhost/Ghost/issues/10922

- adds migrations to...
  1. add `post.type` column
  2. populate `post.type` column based on `post.page` value
  3. drop `post.page` column
- updates all code paths to work with `post.type` in place of `post.page`
- adds `nql-map-key-values` transformer for mapping `page`->`type` in `filter` params when using the v2 API
- modifies importer to handle `post.page`->`post.type` transformation when importing older export files
This commit is contained in:
Kevin Ansfield 2019-09-16 11:51:54 +01:00 committed by GitHub
parent d2bd3975f9
commit e57e19ec31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 628 additions and 212 deletions

View File

@ -23,6 +23,8 @@ const _ = require('lodash'),
replacement: 'primary_author.slug'
}];
const mapNQLKeyValues = require('../../../shared/nql-map-key-values');
/**
* The UrlGenerator class is responsible to generate urls based on a router's conditions.
* It is the component which sits between routers and resources and connects them together.
@ -44,7 +46,22 @@ class UrlGenerator {
// CASE: routers can define custom filters, but not required.
if (this.router.getFilter()) {
this.filter = this.router.getFilter();
this.nql = nql(this.filter, {expansions: EXPANSIONS});
this.nql = nql(this.filter, {
expansions: EXPANSIONS,
transformer: mapNQLKeyValues({
key: {
from: 'page',
to: 'type'
},
values: [{
from: false,
to: 'post'
}, {
from: true,
to: 'page'
}]
})
});
debug('filter', this.filter);
}

View File

@ -8,7 +8,7 @@ module.exports = [
type: 'posts',
modelOptions: {
modelName: 'Post',
filter: 'visibility:public+status:published+page:false',
filter: 'visibility:public+status:published+type:post',
exclude: [
'title',
'mobiledoc',
@ -79,7 +79,7 @@ module.exports = [
'primary_tag',
'primary_author'
],
filter: 'visibility:public+status:published+page:true'
filter: 'visibility:public+status:published+type:page'
},
events: {
add: 'page.published',

View File

@ -8,7 +8,7 @@ module.exports = [
type: 'posts',
modelOptions: {
modelName: 'Post',
filter: 'visibility:public+status:published+page:false',
filter: 'visibility:public+status:published+type:post',
exclude: [
'title',
'mobiledoc',
@ -79,7 +79,7 @@ module.exports = [
'primary_tag',
'primary_author'
],
filter: 'visibility:public+status:published+page:true'
filter: 'visibility:public+status:published+type:page'
},
events: {
add: 'page.published',

View File

@ -8,7 +8,7 @@ module.exports = [
type: 'posts',
modelOptions: {
modelName: 'Post',
filter: 'visibility:public+status:published+page:false',
filter: 'visibility:public+status:published+type:post',
exclude: [
'title',
'mobiledoc',
@ -79,7 +79,7 @@ module.exports = [
'primary_tag',
'primary_author'
],
filter: 'visibility:public+status:published+page:true'
filter: 'visibility:public+status:published+type:page'
},
events: {
add: 'page.published',

View File

@ -1,10 +1,25 @@
const _ = require('lodash');
const debug = require('ghost-ignition').debug('api:canary:utils:serializers:input:pages');
const mapNQLKeyValues = require('../../../../../../shared/nql-map-key-values');
const converters = require('../../../../../lib/mobiledoc/converters');
const url = require('./utils/url');
const localUtils = require('../../index');
const postsMetaSchema = require('../../../../../data/schema').tables.posts_meta;
const replacePageWithType = mapNQLKeyValues({
key: {
from: 'page',
to: 'type'
},
values: [{
from: false,
to: 'post'
}, {
from: true,
to: 'page'
}]
});
function removeMobiledocFormat(frame) {
if (frame.options.formats && frame.options.formats.includes('mobiledoc')) {
frame.options.formats = frame.options.formats.filter((format) => {
@ -62,9 +77,9 @@ function handlePostsMeta(frame) {
*/
const forcePageFilter = (frame) => {
if (frame.options.filter) {
frame.options.filter = `(${frame.options.filter})+page:true`;
frame.options.filter = `(${frame.options.filter})+type:page`;
} else {
frame.options.filter = 'page:true';
frame.options.filter = 'type:page';
}
};
@ -93,6 +108,8 @@ module.exports = {
defaultRelations(frame);
}
frame.options.mongoTransformer = replacePageWithType;
debug(frame.options);
},
@ -130,7 +147,7 @@ module.exports = {
// @NOTE: force storing page
if (options.add) {
frame.data.pages[0].page = true;
frame.data.pages[0].type = 'page';
}
// CASE: Transform short to long format
@ -172,7 +189,7 @@ module.exports = {
destroy(apiConfig, frame) {
frame.options.destroyBy = {
id: frame.options.id,
page: true
type: 'page'
};
defaultFormat(frame);

View File

@ -1,11 +1,26 @@
const _ = require('lodash');
const debug = require('ghost-ignition').debug('api:canary:utils:serializers:input:posts');
const mapNQLKeyValues = require('../../../../../../shared/nql-map-key-values');
const url = require('./utils/url');
const localUtils = require('../../index');
const labs = require('../../../../../services/labs');
const converters = require('../../../../../lib/mobiledoc/converters');
const postsMetaSchema = require('../../../../../data/schema').tables.posts_meta;
const replacePageWithType = mapNQLKeyValues({
key: {
from: 'page',
to: 'type'
},
values: [{
from: false,
to: 'post'
}, {
from: true,
to: 'page'
}]
});
function removeMobiledocFormat(frame) {
if (frame.options.formats && frame.options.formats.includes('mobiledoc')) {
frame.options.formats = frame.options.formats.filter((format) => {
@ -71,9 +86,9 @@ function handlePostsMeta(frame) {
*/
const forcePageFilter = (frame) => {
if (frame.options.filter) {
frame.options.filter = `(${frame.options.filter})+page:false`;
frame.options.filter = `(${frame.options.filter})+type:post`;
} else {
frame.options.filter = 'page:false';
frame.options.filter = 'type:post';
}
};
@ -115,6 +130,8 @@ module.exports = {
defaultRelations(frame);
}
frame.options.mongoTransformer = replacePageWithType;
debug(frame.options);
},
@ -165,7 +182,7 @@ module.exports = {
// @NOTE: force adding post
if (options.add) {
frame.data.posts[0].page = false;
frame.data.posts[0].type = 'post';
}
// CASE: Transform short to long format
@ -205,7 +222,7 @@ module.exports = {
destroy(apiConfig, frame) {
frame.options.destroyBy = {
id: frame.options.id,
page: false
type: 'post'
};
defaultFormat(frame);

View File

@ -108,6 +108,7 @@ const post = (attrs, frame) => {
delete attrs.locale;
delete attrs.visibility;
delete attrs.author;
delete attrs.type;
return attrs;
};

View File

@ -36,6 +36,10 @@ const mapPost = (model, frame) => {
url.forPost(model.id, jsonModel, frame);
if (utils.isContentAPI(frame)) {
// Content api v2 still expects page prop
if (jsonModel.type === 'page') {
jsonModel.page = true;
}
date.forPost(jsonModel);
members.forPost(jsonModel, frame);
}

View File

@ -1,10 +1,25 @@
const _ = require('lodash');
const mapNQLKeyValues = require('../../../../../../shared/nql-map-key-values');
const debug = require('ghost-ignition').debug('api:v2:utils:serializers:input:pages');
const converters = require('../../../../../lib/mobiledoc/converters');
const url = require('./utils/url');
const localUtils = require('../../index');
const postsMetaSchema = require('../../../../../data/schema').tables.posts_meta;
const replacePageWithType = mapNQLKeyValues({
key: {
from: 'page',
to: 'type'
},
values: [{
from: false,
to: 'post'
}, {
from: true,
to: 'page'
}]
});
function removeMobiledocFormat(frame) {
if (frame.options.formats && frame.options.formats.includes('mobiledoc')) {
frame.options.formats = frame.options.formats.filter((format) => {
@ -62,9 +77,9 @@ function handlePostsMeta(frame) {
*/
const forcePageFilter = (frame) => {
if (frame.options.filter) {
frame.options.filter = `(${frame.options.filter})+page:true`;
frame.options.filter = `(${frame.options.filter})+type:page`;
} else {
frame.options.filter = 'page:true';
frame.options.filter = 'type:page';
}
};
@ -93,6 +108,8 @@ module.exports = {
defaultRelations(frame);
}
frame.options.mongoTransformer = replacePageWithType;
debug(frame.options);
},
@ -130,7 +147,7 @@ module.exports = {
// @NOTE: force storing page
if (options.add) {
frame.data.pages[0].page = true;
frame.data.pages[0].type = 'page';
}
// CASE: Transform short to long format
@ -172,7 +189,7 @@ module.exports = {
destroy(apiConfig, frame) {
frame.options.destroyBy = {
id: frame.options.id,
page: true
type: 'page'
};
defaultFormat(frame);

View File

@ -1,4 +1,5 @@
const _ = require('lodash');
const mapNQLKeyValues = require('../../../../../../shared/nql-map-key-values');
const debug = require('ghost-ignition').debug('api:v2:utils:serializers:input:posts');
const url = require('./utils/url');
const localUtils = require('../../index');
@ -6,6 +7,20 @@ const labs = require('../../../../../services/labs');
const converters = require('../../../../../lib/mobiledoc/converters');
const postsMetaSchema = require('../../../../../data/schema').tables.posts_meta;
const replacePageWithType = mapNQLKeyValues({
key: {
from: 'page',
to: 'type'
},
values: [{
from: false,
to: 'post'
}, {
from: true,
to: 'page'
}]
});
function removeMobiledocFormat(frame) {
if (frame.options.formats && frame.options.formats.includes('mobiledoc')) {
frame.options.formats = frame.options.formats.filter((format) => {
@ -71,9 +86,9 @@ function handlePostsMeta(frame) {
*/
const forcePageFilter = (frame) => {
if (frame.options.filter) {
frame.options.filter = `(${frame.options.filter})+page:false`;
frame.options.filter = `(${frame.options.filter})+type:post`;
} else {
frame.options.filter = 'page:false';
frame.options.filter = 'type:post';
}
};
@ -115,6 +130,8 @@ module.exports = {
defaultRelations(frame);
}
frame.options.mongoTransformer = replacePageWithType;
debug(frame.options);
},
@ -165,7 +182,7 @@ module.exports = {
// @NOTE: force adding post
if (options.add) {
frame.data.posts[0].page = false;
frame.data.posts[0].type = 'post';
}
// CASE: Transform short to long format
@ -205,7 +222,7 @@ module.exports = {
destroy(apiConfig, frame) {
frame.options.destroyBy = {
id: frame.options.id,
page: false
type: 'post'
};
defaultFormat(frame);

View File

@ -108,6 +108,7 @@ const post = (attrs, frame) => {
delete attrs.locale;
delete attrs.visibility;
delete attrs.author;
delete attrs.type;
return attrs;
};

View File

@ -36,6 +36,10 @@ const mapPost = (model, frame) => {
url.forPost(model.id, jsonModel, frame);
if (utils.isContentAPI(frame)) {
// Content api v2 still expects page prop
if (jsonModel.type === 'page') {
jsonModel.page = true;
}
date.forPost(jsonModel);
members.forPost(jsonModel, frame);
}

View File

@ -23,6 +23,16 @@ class PostsImporter extends BaseImporter {
if (!validation.validator.isUUID(obj.uuid || '')) {
obj.uuid = uuid.v4();
}
// we used to have post.page=true/false
// we now have post.type='page'/'post'
// give precedence to post.type if both are present
if (_.has(obj, 'page')) {
if (_.isEmpty(obj.type)) {
obj.type = obj.page ? 'page' : 'post';
}
delete obj.page;
}
});
}
@ -166,14 +176,6 @@ class PostsImporter extends BaseImporter {
this.addNestedRelations();
_.each(this.dataToImport, (model) => {
// during 2.28.x we had `post.type` in place of `post.page`
// this needs normalising back to `post.page`
// TODO: switch back to `post.page->type` in v3
if (_.has(model, 'type')) {
model.page = model.type === 'post' ? false : true;
delete model.type;
}
// NOTE: we remember the original post id for disqus
// (see https://github.com/TryGhost/Ghost/issues/8963)

View File

@ -0,0 +1,44 @@
const common = require('../../../../lib/common');
const commands = require('../../../schema').commands;
const createLog = type => msg => common.logging[type](msg);
function createColumnMigration({table, column, dbIsInCorrectState, operation, operationVerb}) {
return function columnMigrations({transacting}) {
return transacting.schema.hasColumn(table, column)
.then(dbIsInCorrectState)
.then((isInCorrectState) => {
const log = createLog(isInCorrectState ? 'warn' : 'info');
log(`${operationVerb} ${table}.${column}`);
if (!isInCorrectState) {
return operation(table, column, transacting);
}
});
};
}
module.exports.up = createColumnMigration({
table: 'posts',
column: 'type',
dbIsInCorrectState(columnExists) {
return columnExists === true;
},
operation: commands.addColumn,
operationVerb: 'Adding'
});
module.exports.down = createColumnMigration({
table: 'posts',
column: 'type',
dbIsInCorrectState(columnExists) {
return columnExists === false;
},
operation: commands.dropColumn,
operationVerb: 'Removing'
});
module.exports.config = {
transaction: true
};

View File

@ -0,0 +1,94 @@
const Promise = require('bluebird');
const toPairs = require('lodash/toPairs');
const common = require('../../../../lib/common');
/*
* @param from: object with a SINGLE entry { 'fromColumn': 'fromValue' }
* @param to: object with a SINGLE entry { 'toColumn': 'toValue' }
*/
const createColumnToColumnMap = ({from, to, tableName}) => (connection) => {
return connection.schema.hasTable(tableName)
.then((tableExists) => {
if (!tableExists) {
common.logging.warn(
`Table ${tableName} does not exist`
);
return;
}
const [fromColumn, fromValue] = toPairs(from)[0];
const [toColumn, toValue] = toPairs(to)[0];
return Promise.all([
connection.schema.hasColumn(tableName, fromColumn),
connection.schema.hasColumn(tableName, toColumn)
]).then(([fromColumnExists, toColumnExists]) => {
if (!fromColumnExists) {
common.logging.warn(
`Table '${tableName}' does not have column '${fromColumn}'`
);
}
if (!toColumnExists) {
common.logging.warn(
`Table '${tableName}' does not have column '${toColumn}'`
);
}
if (!fromColumnExists || !toColumnExists) {
return;
}
common.logging.info(
`Updating ${tableName}, setting "${toColumn}" column to "${toValue}" where "${fromColumn}" column is "${fromValue}"`
);
return connection(tableName)
.where(fromColumn, fromValue)
.update(toColumn, toValue);
});
});
};
const createColumnToColumnMigration = ({tableName, from, to}) => {
return {
up: createColumnToColumnMap({from, to, tableName}),
down: createColumnToColumnMap({from: to, to: from, tableName})
};
};
const pageColumnToPageType = createColumnToColumnMigration({
tableName: 'posts',
from: {
page: true
},
to: {
type: 'page'
}
});
const pageColumnToPostType = createColumnToColumnMigration({
tableName: 'posts',
from: {
page: false
},
to: {
type: 'post'
}
});
module.exports.up = ({transacting}) => {
return Promise.all([
pageColumnToPageType.up(transacting),
pageColumnToPostType.up(transacting)
]);
};
module.exports.down = ({transacting}) => {
return Promise.all([
pageColumnToPageType.down(transacting),
pageColumnToPostType.down(transacting)
]);
};
module.exports.config = {
transaction: true
};

View File

@ -0,0 +1,49 @@
const common = require('../../../../lib/common');
const commands = require('../../../schema').commands;
const createLog = type => msg => common.logging[type](msg);
function createColumnMigration({table, column, dbIsInCorrectState, operation, operationVerb, columnDefinition}) {
return function columnMigrations({transacting}) {
return transacting.schema.hasColumn(table, column)
.then(dbIsInCorrectState)
.then((isInCorrectState) => {
const log = createLog(isInCorrectState ? 'warn' : 'info');
log(`${operationVerb} ${table}.${column}`);
if (!isInCorrectState) {
return operation(table, column, transacting, columnDefinition);
}
});
};
}
module.exports.up = createColumnMigration({
table: 'posts',
column: 'page',
dbIsInCorrectState(columnExists) {
return columnExists === false;
},
operation: commands.dropColumn,
operationVerb: 'Removing'
});
module.exports.down = createColumnMigration({
table: 'posts',
column: 'page',
dbIsInCorrectState(columnExists) {
return columnExists === true;
},
operation: commands.addColumn,
operationVerb: 'Adding',
columnDefinition: {
type: 'bool',
nullable: false,
defaultTo: false
}
});
module.exports.config = {
transaction: true
};

File diff suppressed because one or more lines are too long

View File

@ -19,7 +19,7 @@ module.exports = {
plaintext: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true},
feature_image: {type: 'string', maxlength: 2000, nullable: true},
featured: {type: 'bool', nullable: false, defaultTo: false},
page: {type: 'bool', nullable: false, defaultTo: false},
type: {type: 'string', maxlength: 50, nullable: false, defaultTo: 'post', validations: {isIn: [['post', 'page']]}},
status: {type: 'string', maxlength: 50, nullable: false, defaultTo: 'draft'},
locale: {type: 'string', maxlength: 6, nullable: true},
visibility: {

View File

@ -345,7 +345,8 @@ validate = function validate(value, key, validations, tableName) {
}
validationErrors.push(new common.errors.ValidationError({
message: translation
message: translation,
context: `${tableName}.${key}`
}));
}

View File

@ -682,11 +682,11 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
case 'edit':
return baseOptions.concat(extraOptions, ['id', 'require']);
case 'findOne':
return baseOptions.concat(extraOptions, ['columns', 'require']);
return baseOptions.concat(extraOptions, ['columns', 'require', 'mongoTransformer']);
case 'findAll':
return baseOptions.concat(extraOptions, ['columns']);
return baseOptions.concat(extraOptions, ['columns', 'mongoTransformer']);
case 'findPage':
return baseOptions.concat(extraOptions, ['filter', 'order', 'page', 'limit', 'columns']);
return baseOptions.concat(extraOptions, ['filter', 'order', 'page', 'limit', 'columns', 'mongoTransformer']);
default:
return baseOptions.concat(extraOptions);
}

View File

@ -61,6 +61,7 @@ const filter = function filter(Bookshelf) {
let extra = this.extraFilters(options);
let overrides = this.enforcedFilters(options);
let defaults = this.defaultFilters(options);
let transformer = options.mongoTransformer;
debug('custom', custom);
debug('extra', extra);
@ -81,7 +82,8 @@ const filter = function filter(Bookshelf) {
relations: RELATIONS,
expansions: EXPANSIONS,
overrides: overrides,
defaults: defaults
defaults: defaults,
transformer: transformer
}).querySQL(qb);
});
} catch (err) {

View File

@ -19,7 +19,7 @@ module.exports = function (Bookshelf) {
if (options.context && options.context.public) {
// @TODO use the filter behavior for posts
qb.andWhere('posts.page', '=', false);
qb.andWhere('posts.type', '=', 'post');
qb.andWhere('posts.status', '=', 'published');
}
});
@ -36,7 +36,7 @@ module.exports = function (Bookshelf) {
if (options.context && options.context.public) {
// @TODO use the filter behavior for posts
qb.andWhere('posts.page', '=', false);
qb.andWhere('posts.type', '=', 'post');
qb.andWhere('posts.status', '=', 'published');
}
});

View File

@ -44,7 +44,7 @@ Post = ghostBookshelf.Model.extend({
uuid: uuid.v4(),
status: 'draft',
featured: false,
page: false,
type: 'post',
visibility: 'public'
};
},
@ -75,10 +75,10 @@ Post = ghostBookshelf.Model.extend({
emitChange: function emitChange(event, options = {}) {
let eventToTrigger;
let resourceType = this.get('page') ? 'page' : 'post';
let resourceType = this.get('type');
if (options.usePreviousAttribute) {
resourceType = this.previous('page') ? 'page' : 'post';
resourceType = this.previous('type');
}
eventToTrigger = resourceType + '.' + event;
@ -119,7 +119,7 @@ Post = ghostBookshelf.Model.extend({
model.isScheduled = model.get('status') === 'scheduled';
model.wasPublished = model.previous('status') === 'published';
model.wasScheduled = model.previous('status') === 'scheduled';
model.resourceTypeChanging = model.get('page') !== model.previous('page');
model.resourceTypeChanging = model.get('type') !== model.previous('type');
model.publishedAtHasChanged = model.hasDateChanged('published_at');
model.needsReschedule = model.publishedAtHasChanged && model.isScheduled;
@ -613,7 +613,7 @@ Post = ghostBookshelf.Model.extend({
return null;
}
return options.context && options.context.public ? 'page:false' : 'page:false+status:published';
return options.context && options.context.public ? 'type:post' : 'type:post+status:published';
},
/**
@ -634,7 +634,7 @@ Post = ghostBookshelf.Model.extend({
options.staticPages = _.includes(['true', '1'], options.staticPages);
}
filter = `page:${options.staticPages}`;
filter = `page:${options.staticPages ? 'true' : 'false'}`;
} else if (options.staticPages === 'all') {
filter = 'page:[true, false]';
}

View File

@ -45,7 +45,7 @@ function ping(post) {
if (slackSettings && slackSettings.url && slackSettings.url !== '') {
slackSettings.username = slackSettings.username ? slackSettings.username : 'Ghost';
// Only ping when not a page
if (post.page) {
if (post.type === 'page') {
return;
}

View File

@ -27,7 +27,7 @@ function ping(post) {
title = post.title,
url = urlService.getUrlByResourceId(post.id, {absolute: true});
if (post.page || config.isPrivacyDisabled('useRpcPing') || settingsCache.get('is_private')) {
if (post.type === 'page' || config.isPrivacyDisabled('useRpcPing') || settingsCache.get('is_private')) {
return;
}

View File

@ -0,0 +1,26 @@
# nql-map-key-values
This utility returns a transformer which can be passed to the `@nexes/nql` library to transform queries
### Usage
```js
const nql = require('@nexes/nql');
const mapKeyValues = require('nql-map-key-values');
nql('good:true', {
transformer: mapKeyValues({
key: {
from: 'good',
to: 'bad'
},
values: [{
from: true,
to: false
}, {
from: false,
to: true
}]
});
}).toJSON(); // => {bad: false}
```

View File

@ -0,0 +1,44 @@
const _ = require('lodash');
const nql = require('@nexes/nql');
/*
* Returns the replacement value for input, or input if it doesn't exist
*/
function replaceValue(input, valueMappings) {
const replacer = valueMappings.find(({from}) => from === input);
return replacer && replacer.to || input;
}
function fmap(item, fn) {
return Array.isArray(item) ? item.map(fn) : fn(item);
}
function mapKeysAndValues(input, mapping) {
return nql.utils.mapQuery(input, function (value, key) {
// Ignore everything that has nothing to do with our mapping
if (key !== mapping.key.from) {
return {
[key]: value
};
}
// key: valueA
if (typeof value !== 'object') {
return {
[mapping.key.to]: replaceValue(value, mapping.values)
};
}
// key: { "$in": ['valueA', 'valueB'] }
// key: { "$ne": 'valueA' }
return {
[mapping.key.to]: _.reduce(value, (memo, objValue, objKey) => {
return Object.assign(memo, {
[objKey]: fmap(objValue, item => replaceValue(item, mapping.values))
});
}, {})
};
});
}
module.exports = mapping => input => mapKeysAndValues(input, mapping);

View File

@ -0,0 +1,14 @@
{
"name": "nql-map-key-values",
"version": "0.0.0",
"description": "Map keys and values for nql query objects",
"main": "index.js",
"repository": "https://github.com/TryGhost/Ghost/tree/master/core/shared/nql-map-key-values",
"author": "Ghost Foundation",
"license": "MIT",
"private": true,
"dependencies": {
"@nexes/nql": "0.3.0",
"lodash": "4.17.15"
}
}

View File

@ -83,7 +83,7 @@ describe('Pages API', function () {
.then((model) => {
model.get('title').should.eql(page.title);
model.get('status').should.eql(page.status);
model.get('page').should.eql(true);
model.get('type').should.eql('page');
});
});
@ -116,7 +116,7 @@ describe('Pages API', function () {
}, testUtils.context.internal);
})
.then((model) => {
model.get('page').should.eql(true);
model.get('type').should.eql('page');
});
});

View File

@ -31,6 +31,8 @@ const expectedProperties = {
.without('visibility')
.without('locale')
.without('page')
// v2 API doesn't return new type field
.without('type')
// deprecated
.without('author_id')
// always returns computed properties
@ -50,6 +52,8 @@ const expectedProperties = {
.without('visibility')
.without('locale')
.without('page')
// v2 API doesn't return new type field
.without('type')
// deprecated
.without('author_id')
// always returns computed properties

View File

@ -23,6 +23,8 @@ const expectedProperties = {
.without('locale', 'visibility')
// These fields aren't useful as they always have known values
.without('status')
// v2 API doesn't return new type field
.without('type')
// @TODO: https://github.com/TryGhost/Ghost/issues/10335
// .without('page')
// v2 returns a calculated excerpt field

View File

@ -12,7 +12,7 @@ const localUtils = require('./utils');
const ghost = testUtils.startGhost;
describe('Schedules API', function () {
describe('Canary Schedules API', function () {
const resources = [];
let request;
@ -80,7 +80,7 @@ describe('Schedules API', function () {
published_at: moment().add(30, 'seconds').toDate(),
status: 'scheduled',
slug: 'fifth',
page: true
type: 'page'
}));
return Promise.mapSeries(resources, function (post) {

View File

@ -25,6 +25,7 @@ const expectedProperties = {
.without('status')
// @TODO: https://github.com/TryGhost/Ghost/issues/10335
// .without('page')
.without('type')
// canary returns a calculated excerpt field
.concat('excerpt')
// returns meta fields from `posts_meta` schema

View File

@ -12,7 +12,7 @@ const localUtils = require('./utils');
const ghost = testUtils.startGhost;
describe('Schedules API', function () {
describe('v2 Schedules API', function () {
const resources = [];
let request;
@ -80,7 +80,7 @@ describe('Schedules API', function () {
published_at: moment().add(30, 'seconds').toDate(),
status: 'scheduled',
slug: 'fifth',
page: true
type: 'page'
}));
return Promise.mapSeries(resources, function (post) {

View File

@ -25,6 +25,7 @@ const expectedProperties = {
.without('status')
// @TODO: https://github.com/TryGhost/Ghost/issues/10335
// .without('page')
.without('type')
// v2 returns a calculated excerpt field
.concat('excerpt')
// returns meta fields from `posts_meta` schema

View File

@ -12,7 +12,7 @@ const localUtils = require('./utils');
const ghost = testUtils.startGhost;
describe('Schedules API', function () {
describe('v3 Schedules API', function () {
const resources = [];
let request;
@ -80,7 +80,7 @@ describe('Schedules API', function () {
published_at: moment().add(30, 'seconds').toDate(),
status: 'scheduled',
slug: 'fifth',
page: true
type: 'page'
}));
return Promise.mapSeries(resources, function (post) {

View File

@ -25,6 +25,7 @@ const expectedProperties = {
.without('status')
// @TODO: https://github.com/TryGhost/Ghost/issues/10335
// .without('page')
.without('type')
// v3 returns a calculated excerpt field
.concat('excerpt')
// returns meta fields from `posts_meta` schema

View File

@ -528,21 +528,21 @@ describe('Post Model', function () {
post.id.should.equal(postId);
post.status.should.equal('draft');
return models.Post.edit({page: 1}, _.extend({}, context, {id: postId}));
return models.Post.edit({type: 'page'}, _.extend({}, context, {id: postId}));
}).then(function (edited) {
should.exist(edited);
edited.attributes.status.should.equal('draft');
edited.attributes.page.should.equal(true);
edited.attributes.type.should.equal('page');
Object.keys(eventsTriggered).length.should.eql(2);
should.exist(eventsTriggered['post.deleted']);
should.exist(eventsTriggered['page.added']);
return models.Post.edit({page: 0}, _.extend({}, context, {id: postId}));
return models.Post.edit({type: 'post'}, _.extend({}, context, {id: postId}));
}).then(function (edited) {
should.exist(edited);
edited.attributes.status.should.equal('draft');
edited.attributes.page.should.equal(false);
edited.attributes.type.should.equal('post');
Object.keys(eventsTriggered).length.should.eql(4);
should.exist(eventsTriggered['post.deleted']);
@ -562,25 +562,25 @@ describe('Post Model', function () {
post.status.should.equal('draft');
return models.Post.edit({
page: 1,
type: 'page',
status: 'scheduled',
published_at: moment().add(10, 'days')
}, _.extend({}, context, {id: post.id}));
}).then(function (edited) {
should.exist(edited);
edited.attributes.status.should.equal('scheduled');
edited.attributes.page.should.equal(true);
edited.attributes.type.should.equal('page');
Object.keys(eventsTriggered).length.should.eql(3);
should.exist(eventsTriggered['post.deleted']);
should.exist(eventsTriggered['page.added']);
should.exist(eventsTriggered['page.scheduled']);
return models.Post.edit({page: 0}, _.extend({}, context, {id: edited.id}));
return models.Post.edit({type: 'post'}, _.extend({}, context, {id: edited.id}));
}).then(function (edited) {
should.exist(edited);
edited.attributes.status.should.equal('scheduled');
edited.attributes.page.should.equal(false);
edited.attributes.type.should.equal('post');
Object.keys(eventsTriggered).length.should.eql(7);
should.exist(eventsTriggered['page.unscheduled']);
@ -602,11 +602,11 @@ describe('Post Model', function () {
post.id.should.equal(postId);
post.status.should.equal('published');
return models.Post.edit({page: 1}, _.extend({}, context, {id: postId}));
return models.Post.edit({type: 'page'}, _.extend({}, context, {id: postId}));
}).then(function (edited) {
should.exist(edited);
edited.attributes.status.should.equal('published');
edited.attributes.page.should.equal(true);
edited.attributes.type.should.equal('page');
Object.keys(eventsTriggered).length.should.eql(4);
should.exist(eventsTriggered['post.unpublished']);
@ -614,11 +614,11 @@ describe('Post Model', function () {
should.exist(eventsTriggered['page.added']);
should.exist(eventsTriggered['page.published']);
return models.Post.edit({page: 0}, _.extend({}, context, {id: postId}));
return models.Post.edit({type: 'post'}, _.extend({}, context, {id: postId}));
}).then(function (edited) {
should.exist(edited);
edited.attributes.status.should.equal('published');
edited.attributes.page.should.equal(false);
edited.attributes.type.should.equal('post');
Object.keys(eventsTriggered).length.should.eql(8);
should.exist(eventsTriggered['page.unpublished']);
@ -640,11 +640,11 @@ describe('Post Model', function () {
post.id.should.equal(postId);
post.status.should.equal('draft');
return models.Post.edit({page: 1, status: 'published'}, _.extend({}, context, {id: postId}));
return models.Post.edit({type: 'page', status: 'published'}, _.extend({}, context, {id: postId}));
}).then(function (edited) {
should.exist(edited);
edited.attributes.status.should.equal('published');
edited.attributes.page.should.equal(true);
edited.attributes.type.should.equal('page');
Object.keys(eventsTriggered).length.should.eql(5);
should.exist(eventsTriggered['post.deleted']);
@ -653,11 +653,11 @@ describe('Post Model', function () {
should.exist(eventsTriggered['tag.attached']);
should.exist(eventsTriggered['user.attached']);
return models.Post.edit({page: 0, status: 'draft'}, _.extend({}, context, {id: postId}));
return models.Post.edit({type: 'post', status: 'draft'}, _.extend({}, context, {id: postId}));
}).then(function (edited) {
should.exist(edited);
edited.attributes.status.should.equal('draft');
edited.attributes.page.should.equal(false);
edited.attributes.type.should.equal('post');
Object.keys(eventsTriggered).length.should.eql(8);
should.exist(eventsTriggered['page.unpublished']);
@ -1173,7 +1173,7 @@ describe('Post Model', function () {
page = results.toJSON();
page.id.should.equal(firstItemData.id);
page.status.should.equal('published');
page.page.should.be.true();
page.type.should.equal('page');
// Destroy the page
return results.destroy(firstItemData);

View File

@ -153,7 +153,7 @@ describe('Integration - Web - Site', function () {
response.statusCode.should.eql(200);
response.template.should.eql('tag');
postSpy.args[0][0].options.filter.should.eql('(tags:\'bacon\'+tags.visibility:public)+page:false');
postSpy.args[0][0].options.filter.should.eql('(tags:\'bacon\'+tags.visibility:public)+type:post');
postSpy.args[0][0].options.page.should.eql(1);
postSpy.args[0][0].options.limit.should.eql(2);
});
@ -1851,7 +1851,7 @@ describe('Integration - Web - Site', function () {
response.statusCode.should.eql(200);
response.template.should.eql('tag');
postSpy.args[0][0].options.filter.should.eql('(tags:\'bacon\'+tags.visibility:public)+page:false');
postSpy.args[0][0].options.filter.should.eql('(tags:\'bacon\'+tags.visibility:public)+type:post');
postSpy.args[0][0].options.page.should.eql(1);
postSpy.args[0][0].options.limit.should.eql(2);
});
@ -3551,7 +3551,7 @@ describe('Integration - Web - Site', function () {
response.statusCode.should.eql(200);
response.template.should.eql('tag');
postSpy.args[0][0].options.filter.should.eql('(tags:\'bacon\'+tags.visibility:public)+page:false');
postSpy.args[0][0].options.filter.should.eql('(tags:\'bacon\'+tags.visibility:public)+type:post');
postSpy.args[0][0].options.page.should.eql(1);
postSpy.args[0][0].options.limit.should.eql(2);
});

View File

@ -13,7 +13,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('combine filters', function () {
@ -27,7 +27,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(status:published+tag:eins)+page:true');
frame.options.filter.should.eql('(status:published+tag:eins)+type:page');
});
it('combine filters', function () {
@ -41,7 +41,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:false+tag:eins)+page:true');
frame.options.filter.should.eql('(page:false+tag:eins)+type:page');
});
it('combine filters', function () {
@ -55,7 +55,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+page:true');
frame.options.filter.should.eql('(page:false)+type:page');
});
it('remove mobiledoc option from formats', function () {
@ -87,7 +87,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('content api default', function () {
@ -107,7 +107,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('admin api default', function () {
@ -127,7 +127,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+status:[draft,published,scheduled]');
frame.options.filter.should.eql('(type:page)+status:[draft,published,scheduled]');
});
it('custom page filter', function () {
@ -142,7 +142,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+page:true');
frame.options.filter.should.eql('(page:false)+type:page');
});
it('custom status filter', function () {
@ -163,7 +163,7 @@ describe('Unit: canary/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(status:draft)+page:true');
frame.options.filter.should.eql('(status:draft)+type:page');
});
it('remove mobiledoc option from formats', function () {

View File

@ -21,7 +21,7 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('page:false');
frame.options.filter.should.eql('type:post');
});
it('should not work for non public context', function () {
@ -36,7 +36,7 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
should.equal(frame.options.filter, '(page:false)+status:[draft,published,scheduled]');
should.equal(frame.options.filter, '(type:post)+status:[draft,published,scheduled]');
});
it('combine filters', function () {
@ -56,7 +56,7 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(status:published+tag:eins)+page:false');
frame.options.filter.should.eql('(status:published+tag:eins)+type:post');
});
it('combine filters', function () {
@ -76,7 +76,7 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:true+tag:eins)+page:false');
frame.options.filter.should.eql('(page:true+tag:eins)+type:post');
});
it('combine filters', function () {
@ -96,7 +96,7 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+page:false');
frame.options.filter.should.eql('(page:true)+type:post');
});
it('combine filters', function () {
@ -116,7 +116,7 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('((page:true,page:false))+page:false');
frame.options.filter.should.eql('((page:true,page:false))+type:post');
});
it('remove mobiledoc option from formats', function () {
@ -137,7 +137,7 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
});
describe('read', function () {
it('with apiType of "content" it forces page filter', function () {
it('with apiType of "content" it forces type filter', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
@ -146,24 +146,24 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('page:false');
frame.options.filter.should.eql('type:post');
});
it('with apiType of "content" it forces page false filter', function () {
it('with apiType of "content" it forces type:post filter', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
filter: 'page:true'
filter: 'type:page'
},
data: {}
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+page:false');
frame.options.filter.should.eql('(type:page)+type:post');
});
it('with apiType of "admin" it forces page & status false filter', function () {
it('with apiType of "admin" it forces type & status false filter', function () {
const apiConfig = {};
const frame = {
apiType: 'admin',
@ -179,10 +179,10 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+status:[draft,published,scheduled]');
frame.options.filter.should.eql('(type:post)+status:[draft,published,scheduled]');
});
it('with apiType of "admin" it forces page filter & respects custom status filter', function () {
it('with apiType of "admin" it forces type:post filter & respects custom status filter', function () {
const apiConfig = {};
const frame = {
apiType: 'admin',
@ -199,7 +199,7 @@ describe('Unit: canary/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(status:draft)+page:false');
frame.options.filter.should.eql('(status:draft)+type:post');
});
it('remove mobiledoc option from formats', function () {

View File

@ -13,7 +13,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('combine filters', function () {
@ -27,7 +27,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(status:published+tag:eins)+page:true');
frame.options.filter.should.eql('(status:published+tag:eins)+type:page');
});
it('combine filters', function () {
@ -41,7 +41,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:false+tag:eins)+page:true');
frame.options.filter.should.eql('(page:false+tag:eins)+type:page');
});
it('combine filters', function () {
@ -55,7 +55,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+page:true');
frame.options.filter.should.eql('(page:false)+type:page');
});
it('remove mobiledoc option from formats', function () {
@ -87,7 +87,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('content api default', function () {
@ -107,7 +107,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('admin api default', function () {
@ -127,7 +127,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+status:[draft,published,scheduled]');
frame.options.filter.should.eql('(type:page)+status:[draft,published,scheduled]');
});
it('custom page filter', function () {
@ -142,7 +142,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+page:true');
frame.options.filter.should.eql('(page:false)+type:page');
});
it('custom status filter', function () {
@ -163,7 +163,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(status:draft)+page:true');
frame.options.filter.should.eql('(status:draft)+type:page');
});
it('remove mobiledoc option from formats', function () {

View File

@ -21,7 +21,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('page:false');
frame.options.filter.should.eql('type:post');
});
it('should not work for non public context', function () {
@ -36,7 +36,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
should.equal(frame.options.filter, '(page:false)+status:[draft,published,scheduled]');
should.equal(frame.options.filter, '(type:post)+status:[draft,published,scheduled]');
});
it('combine filters', function () {
@ -56,7 +56,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(status:published+tag:eins)+page:false');
frame.options.filter.should.eql('(status:published+tag:eins)+type:post');
});
it('combine filters', function () {
@ -76,7 +76,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:true+tag:eins)+page:false');
frame.options.filter.should.eql('(page:true+tag:eins)+type:post');
});
it('combine filters', function () {
@ -96,7 +96,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+page:false');
frame.options.filter.should.eql('(page:true)+type:post');
});
it('combine filters', function () {
@ -116,7 +116,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('((page:true,page:false))+page:false');
frame.options.filter.should.eql('((page:true,page:false))+type:post');
});
it('remove mobiledoc option from formats', function () {
@ -137,7 +137,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
});
describe('read', function () {
it('with apiType of "content" it forces page filter', function () {
it('with apiType of "content" it forces type filter', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
@ -146,24 +146,24 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('page:false');
frame.options.filter.should.eql('type:post');
});
it('with apiType of "content" it forces page false filter', function () {
it('with apiType of "content" it forces type:post filter', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
filter: 'page:true'
filter: 'type:page'
},
data: {}
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+page:false');
frame.options.filter.should.eql('(type:page)+type:post');
});
it('with apiType of "admin" it forces page & status false filter', function () {
it('with apiType of "admin" it forces type & status false filter', function () {
const apiConfig = {};
const frame = {
apiType: 'admin',
@ -179,10 +179,10 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+status:[draft,published,scheduled]');
frame.options.filter.should.eql('(type:post)+status:[draft,published,scheduled]');
});
it('with apiType of "admin" it forces page filter & respects custom status filter', function () {
it('with apiType of "admin" it forces type:post filter & respects custom status filter', function () {
const apiConfig = {};
const frame = {
apiType: 'admin',
@ -199,7 +199,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(status:draft)+page:false');
frame.options.filter.should.eql('(status:draft)+type:post');
});
it('remove mobiledoc option from formats', function () {

View File

@ -1,7 +1,7 @@
const should = require('should');
const serializers = require('../../../../../../../server/api/canary/utils/serializers');
const serializers = require('../../../../../../../server/api/v2/utils/serializers');
describe('Unit: v3/utils/serializers/input/pages', function () {
describe('Unit: v2/utils/serializers/input/pages', function () {
describe('browse', function () {
it('default', function () {
const apiConfig = {};
@ -13,7 +13,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('combine filters', function () {
@ -27,7 +27,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(status:published+tag:eins)+page:true');
frame.options.filter.should.eql('(status:published+tag:eins)+type:page');
});
it('combine filters', function () {
@ -41,7 +41,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:false+tag:eins)+page:true');
frame.options.filter.should.eql('(page:false+tag:eins)+type:page');
});
it('combine filters', function () {
@ -55,7 +55,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+page:true');
frame.options.filter.should.eql('(page:false)+type:page');
});
it('remove mobiledoc option from formats', function () {
@ -87,7 +87,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('content api default', function () {
@ -107,7 +107,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('page:true');
frame.options.filter.should.eql('type:page');
});
it('admin api default', function () {
@ -127,7 +127,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+status:[draft,published,scheduled]');
frame.options.filter.should.eql('(type:page)+status:[draft,published,scheduled]');
});
it('custom page filter', function () {
@ -142,7 +142,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+page:true');
frame.options.filter.should.eql('(page:false)+type:page');
});
it('custom status filter', function () {
@ -163,7 +163,7 @@ describe('Unit: v3/utils/serializers/input/pages', function () {
};
serializers.input.pages.read(apiConfig, frame);
frame.options.filter.should.eql('(status:draft)+page:true');
frame.options.filter.should.eql('(status:draft)+type:page');
});
it('remove mobiledoc option from formats', function () {

View File

@ -1,9 +1,9 @@
const should = require('should');
const sinon = require('sinon');
const serializers = require('../../../../../../../server/api/canary/utils/serializers');
const serializers = require('../../../../../../../server/api/v2/utils/serializers');
const urlUtils = require('../../../../../../utils/urlUtils');
describe('Unit: v3/utils/serializers/input/posts', function () {
describe('Unit: v2/utils/serializers/input/posts', function () {
describe('browse', function () {
it('default', function () {
const apiConfig = {};
@ -21,7 +21,7 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('page:false');
frame.options.filter.should.eql('type:post');
});
it('should not work for non public context', function () {
@ -36,7 +36,7 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
should.equal(frame.options.filter, '(page:false)+status:[draft,published,scheduled]');
should.equal(frame.options.filter, '(type:post)+status:[draft,published,scheduled]');
});
it('combine filters', function () {
@ -56,7 +56,7 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(status:published+tag:eins)+page:false');
frame.options.filter.should.eql('(status:published+tag:eins)+type:post');
});
it('combine filters', function () {
@ -76,7 +76,7 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:true+tag:eins)+page:false');
frame.options.filter.should.eql('(page:true+tag:eins)+type:post');
});
it('combine filters', function () {
@ -96,7 +96,7 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+page:false');
frame.options.filter.should.eql('(page:true)+type:post');
});
it('combine filters', function () {
@ -116,7 +116,7 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.filter.should.eql('((page:true,page:false))+page:false');
frame.options.filter.should.eql('((page:true,page:false))+type:post');
});
it('remove mobiledoc option from formats', function () {
@ -137,7 +137,7 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
});
describe('read', function () {
it('with apiType of "content" it forces page filter', function () {
it('with apiType of "content" it forces type filter', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
@ -146,24 +146,24 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('page:false');
frame.options.filter.should.eql('type:post');
});
it('with apiType of "content" it forces page false filter', function () {
it('with apiType of "content" it forces type:post filter', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
filter: 'page:true'
filter: 'type:page'
},
data: {}
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(page:true)+page:false');
frame.options.filter.should.eql('(type:page)+type:post');
});
it('with apiType of "admin" it forces page & status false filter', function () {
it('with apiType of "admin" it forces type & status false filter', function () {
const apiConfig = {};
const frame = {
apiType: 'admin',
@ -179,10 +179,10 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(page:false)+status:[draft,published,scheduled]');
frame.options.filter.should.eql('(type:post)+status:[draft,published,scheduled]');
});
it('with apiType of "admin" it forces page filter & respects custom status filter', function () {
it('with apiType of "admin" it forces type:post filter & respects custom status filter', function () {
const apiConfig = {};
const frame = {
apiType: 'admin',
@ -199,7 +199,7 @@ describe('Unit: v3/utils/serializers/input/posts', function () {
};
serializers.input.posts.read(apiConfig, frame);
frame.options.filter.should.eql('(status:draft)+page:false');
frame.options.filter.should.eql('(status:draft)+type:post');
});
it('remove mobiledoc option from formats', function () {

View File

@ -4,7 +4,7 @@ const PostsImporter = require('../../../../../../server/data/importer/importers/
describe('PostsImporter', function () {
describe('#beforeImport', function () {
it('converts post.type to post.page', function () {
it('converts post.page to post.type', function () {
const fakePosts = [{
slug: 'page-false',
page: false
@ -25,27 +25,67 @@ describe('PostsImporter', function () {
const pageFalse = find(importer.dataToImport, {slug: 'page-false'});
should.exist(pageFalse);
should.exist(pageFalse.page, 'pageFalse.page should exist');
should.not.exist(pageFalse.type, 'pageFalse.type should not exist');
pageFalse.page.should.equal(false);
should.not.exist(pageFalse.page, 'pageFalse.page should not exist');
should.exist(pageFalse.type, 'pageFalse.type should exist');
pageFalse.type.should.equal('post');
const pageTrue = find(importer.dataToImport, {slug: 'page-true'});
should.exist(pageTrue);
should.exist(pageTrue.page, 'pageTrue.page should exist');
should.not.exist(pageTrue.type, 'pageTrue.type should not exist');
pageTrue.page.should.equal(true);
should.not.exist(pageTrue.page, 'pageTrue.page should not exist');
should.exist(pageTrue.type, 'pageTrue.type should exist');
pageTrue.type.should.equal('page');
const typePost = find(importer.dataToImport, {slug: 'type-post'});
should.exist(typePost);
should.exist(typePost.page, 'typePost.page should exist');
should.not.exist(typePost.type, 'typePost.type should not exist');
typePost.page.should.equal(false);
should.not.exist(typePost.page, 'typePost.page should not exist');
should.exist(typePost.type, 'typePost.type should exist');
typePost.type.should.equal('post');
const typePage = find(importer.dataToImport, {slug: 'type-page'});
should.exist(typePage);
should.exist(typePage.page, 'typePage.page should exist');
should.not.exist(typePage.type, 'typePage.type should not exist');
typePage.page.should.equal(true);
should.not.exist(typePage.page, 'typePage.page should not exist');
should.exist(typePage.type, 'typePage.type should exist');
typePage.type.should.equal('page');
});
it('gives precedence to post.type when post.page is also present', function () {
const fakePosts = [{
slug: 'page-false-type-page',
page: false,
type: 'page'
}, {
slug: 'page-true-type-page',
page: true,
type: 'page'
}, {
slug: 'page-false-type-post',
page: false,
type: 'post'
}, {
slug: 'page-true-type-post',
page: true,
type: 'post'
}];
const importer = new PostsImporter({posts: fakePosts});
importer.beforeImport();
const pageFalseTypePage = find(importer.dataToImport, {slug: 'page-false-type-page'});
should.exist(pageFalseTypePage);
pageFalseTypePage.type.should.equal('page', 'pageFalseTypePage.type');
const pageTrueTypePage = find(importer.dataToImport, {slug: 'page-true-type-page'});
should.exist(pageTrueTypePage);
pageTrueTypePage.type.should.equal('page', 'pageTrueTypePage.type');
const pageFalseTypePost = find(importer.dataToImport, {slug: 'page-false-type-post'});
should.exist(pageFalseTypePost);
pageFalseTypePost.type.should.equal('post', 'pageFalseTypePost.type');
const pageTrueTypePost = find(importer.dataToImport, {slug: 'page-true-type-post'});
should.exist(pageTrueTypePost);
pageTrueTypePost.type.should.equal('post', 'pageTrueTypePost.type');
});
});
});

View File

@ -19,8 +19,8 @@ var should = require('should'),
*/
describe('DB version integrity', function () {
// Only these variables should need updating
const currentSchemaHash = '964bf174df19bf563602b6c194f34cfe';
const currentFixturesHash = '4e08bb27bf16338b6eebad1f92a247d1';
const currentSchemaHash = '6d99c4ed8317240d392eb2046df10368';
const currentFixturesHash = 'a7152a9f4a59d30e0ccf7785fd6a8cc9';
// If this test is failing, then it is likely a change has been made that requires a DB version bump,
// and the values above will need updating as confirmation

View File

@ -81,26 +81,22 @@ describe('Validation', function () {
});
it('transforms 0 and 1', function () {
const post = models.Post.forge(testUtils.DataGenerator.forKnex.createPost({slug: 'test', featured: 0, page: 1}));
const post = models.Post.forge(testUtils.DataGenerator.forKnex.createPost({slug: 'test', featured: 0}));
post.get('featured').should.eql(0);
post.get('page').should.eql(1);
return validation.validateSchema('posts', post, {method: 'insert'})
.then(function () {
post.get('featured').should.eql(false);
post.get('page').should.eql(true);
});
});
it('keeps true or false', function () {
const post = models.Post.forge(testUtils.DataGenerator.forKnex.createPost({slug: 'test', featured: true, page: false}));
const post = models.Post.forge(testUtils.DataGenerator.forKnex.createPost({slug: 'test', featured: true}));
post.get('featured').should.eql(true);
post.get('page').should.eql(false);
return validation.validateSchema('posts', post, {method: 'insert'})
.then(function () {
post.get('featured').should.eql(true);
post.get('page').should.eql(false);
});
});
});

View File

@ -45,21 +45,21 @@ describe('Unit: models/post', function () {
withRelated: ['tags']
}).then(() => {
queries.length.should.eql(2);
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` = ?))');
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`.`type` = ? and `posts`.`status` = ?))');
queries[0].bindings.should.eql([
testUtils.filterData.data.posts[3].id,
'photo',
'video',
false,
'post',
'published'
]);
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 ?');
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`.`type` = ? 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 ?');
queries[1].bindings.should.eql([
testUtils.filterData.data.posts[3].id,
'photo',
'video',
false,
'post',
'published',
3
]);
@ -80,21 +80,21 @@ describe('Unit: models/post', function () {
withRelated: ['authors', 'tags']
}).then(() => {
queries.length.should.eql(2);
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` = ?))');
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`.`type` = ? and `posts`.`status` = ?))');
queries[0].bindings.should.eql([
'hash-audio',
'leslie',
'pat',
false,
'post',
'published'
]);
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 ?');
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`.`type` = ? 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 ?');
queries[1].bindings.should.eql([
'hash-audio',
'leslie',
'pat',
false,
'post',
'published',
15
]);
@ -116,17 +116,17 @@ describe('Unit: models/post', function () {
withRelated: ['tags']
}).then(() => {
queries.length.should.eql(2);
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where (`posts`.`published_at` > ? and (`posts`.`page` = ? and `posts`.`status` = ?))');
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where (`posts`.`published_at` > ? and (`posts`.`type` = ? and `posts`.`status` = ?))');
queries[0].bindings.should.eql([
'2015-07-20',
false,
'post',
'published'
]);
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 ?');
queries[1].sql.should.eql('select `posts`.* from `posts` where (`posts`.`published_at` > ? and (`posts`.`type` = ? 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 ?');
queries[1].bindings.should.eql([
'2015-07-20',
false,
'post',
'published',
5
]);
@ -148,19 +148,19 @@ describe('Unit: models/post', function () {
withRelated: ['tags']
}).then(() => {
queries.length.should.eql(2);
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` = ?))');
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`.`type` = ? and `posts`.`status` = ?))');
queries[0].bindings.should.eql([
'photo',
'public',
false,
'post',
'published'
]);
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 ?');
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`.`type` = ? 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 ?');
queries[1].bindings.should.eql([
'photo',
'public',
false,
'post',
'published',
15
]);
@ -181,19 +181,19 @@ describe('Unit: models/post', function () {
withRelated: ['authors']
}).then(() => {
queries.length.should.eql(2);
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` = ?))');
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`.`type` = ? and `posts`.`status` = ?))');
queries[0].bindings.should.eql([
'leslie',
'public',
false,
'post',
'published'
]);
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 ?');
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`.`type` = ? 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 ?');
queries[1].bindings.should.eql([
'leslie',
'public',
false,
'post',
'published',
15
]);
@ -224,20 +224,20 @@ describe('Unit: models/post', function () {
}
}).then(() => {
queries.length.should.eql(2);
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`status` in (?, ?) and `posts`.`status` = ?) and (`posts`.`page` = ?))');
queries[0].sql.should.eql('select count(distinct posts.id) as aggregate from `posts` where ((`posts`.`status` in (?, ?) and `posts`.`status` = ?) and (`posts`.`type` = ?))');
queries[0].bindings.should.eql([
'published',
'draft',
'published',
false
'post'
]);
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');
queries[1].sql.should.eql('select `posts`.* from `posts` where ((`posts`.`status` in (?, ?) and `posts`.`status` = ?) and (`posts`.`type` = ?)) 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');
queries[1].bindings.should.eql([
'published',
'draft',
'published',
false
'post'
]);
});
});
@ -322,7 +322,7 @@ describe('Unit: models/post', function () {
should(filter).equal(null);
});
it('returns page:false filter for public context', function () {
it('returns type:post filter for public context', function () {
const options = {
context: {
public: true
@ -331,17 +331,17 @@ describe('Unit: models/post', function () {
const filter = defaultFilters({}, options);
filter.should.equal('page:false');
filter.should.equal('type:post');
});
it('returns page:false+status:published filter for non public context', function () {
it('returns type:post+status:published filter for non public context', function () {
const options = {
context: 'user'
};
const filter = defaultFilters({}, options);
filter.should.equal('page:false+status:published');
filter.should.equal('type:post+status:published');
});
});
});

View File

@ -16,7 +16,7 @@ describe('RSS: Generate Feed', function () {
posts = _.cloneDeep(testUtils.DataGenerator.forKnex.posts);
posts = _.filter(posts, function filter(post) {
return post.status === 'published' && post.page === false;
return post.status === 'published' && post.type === 'post';
});
_.each(posts, function (post) {

View File

@ -192,7 +192,7 @@ describe('Slack', function () {
});
it('does not make a request if post is a page', function () {
const post = testUtils.DataGenerator.forKnex.createPost({page: true});
const post = testUtils.DataGenerator.forKnex.createPost({type: 'page'});
isPostStub.returns(true);
settingsCacheStub.withArgs('slack').returns(slackObjWithUrl);

View File

@ -74,14 +74,14 @@ DataGenerator.Content = {
title: 'This is a static page',
slug: 'static-page-test',
mobiledoc: DataGenerator.markdownToMobiledoc('<h1>Static page test is what this is for.</h1><p>Hopefully you don\'t find it a bore.</p>'),
page: true
type: 'page'
},
{
id: ObjectId.generate(),
title: 'This is a draft static page',
slug: 'static-page-draft',
mobiledoc: DataGenerator.markdownToMobiledoc('<h1>Static page test is what this is for.</h1><p>Hopefully you don\'t find it a bore.</p>'),
page: true,
type: 'page',
status: 'draft'
},
{
@ -468,7 +468,7 @@ DataGenerator.forKnex = (function () {
status: 'published',
feature_image: null,
featured: false,
page: false,
type: 'post',
slug: 'slug',
author_id: DataGenerator.Content.users[0].id,
updated_at: new Date(),