diff --git a/README.md b/README.md index 7e887480..bc318116 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,12 @@ To run a local zip file through the checks: `gscan /path/to/theme.zip -z` -By default, GScan scans themes for the latest Ghost version compatibility. You can also specify a Ghost version by using the following parameters (for Ghost 1.0, 2.0 and 3.0): +By default, GScan scans themes for the latest Ghost version compatibility. You can also specify a Ghost version by using the following parameters (for Ghost 1.0, 2.0, 3.0 and 4.0): `--v1` or `-1` `--v2` or `-2` `--v3` or `-3` +`--v4` or `-4` Use the `--canary` parameter to check for the upcoming Ghost version. @@ -61,9 +62,9 @@ gscan.checkZip({ path: 'path-to-zip', // if you need to check the theme for a different // major Ghost version, you can pass it. Currently - // v1, which is Ghost 1.0 is supported. Default is - // the latest Ghost version 2.0: - // checkVersion: 'v1', + // v1, v2, v3 and v4 are supported. Default is + // the latest Ghost version 3.0: + // checkVersion: 'v3', name: 'my-theme' }).then(function (result) { console.log(result); diff --git a/app/tpl/index.hbs b/app/tpl/index.hbs index be66f9f5..b3874c13 100644 --- a/app/tpl/index.hbs +++ b/app/tpl/index.hbs @@ -29,8 +29,9 @@
+ output.results.fail['GS001-DEPR-MD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-MD'].failures.length.should.eql(1); + + // {{image}} + output.results.fail['GS001-DEPR-IMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-IMG'].failures.length.should.eql(2); + + // {{cover}} + output.results.fail['GS001-DEPR-COV'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-COV'].failures.length.should.eql(3); + + // {{primary_author.image}} + output.results.fail['GS001-DEPR-AIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AIMG'].failures.length.should.eql(2); + + // {{post.image}} + output.results.fail['GS001-DEPR-PIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PIMG'].failures.length.should.eql(1); + + // {{@blog.cover}} + output.results.fail['GS001-DEPR-BC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-BC'].failures.length.should.eql(1); + + // {{author.cover}} + output.results.fail['GS001-DEPR-AC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AC'].failures.length.should.eql(2); + + // {{post.author.cover}} + output.results.fail['GS001-DEPR-PAC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAC'].failures.length.should.eql(1); + + // {{post.author.image}} + output.results.fail['GS001-DEPR-PAIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAIMG'].failures.length.should.eql(1); + + // {{tag.image}} + output.results.fail['GS001-DEPR-TIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-TIMG'].failures.length.should.eql(1); + + // {{posts.tags.[4].image}} + output.results.fail['GS001-DEPR-PTIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PTIMG'].failures.length.should.eql(1); + + // {{tags.[4].image}} + output.results.fail['GS001-DEPR-TSIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-TSIMG'].failures.length.should.eql(1); + + // {{#if image}} + output.results.fail['GS001-DEPR-CON-IMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-IMG'].failures.length.should.eql(1); + + // {{#if cover}} + output.results.fail['GS001-DEPR-CON-COV'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-COV'].failures.length.should.eql(1); + + // {{#if tag.image}} + output.results.fail['GS001-DEPR-CON-TIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-TIMG'].failures.length.should.eql(1); + + // {{#if tags.[#].image}} + output.results.fail['GS001-DEPR-CON-TSIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-TSIMG'].failures.length.should.eql(1); + + // {{#if post.tags.[#].image}} + output.results.fail['GS001-DEPR-CON-PTIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-PTIMG'].failures.length.should.eql(1); + + // {{@blog.posts_per_page}} + output.results.fail['GS001-DEPR-PPP'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PPP'].failures.length.should.eql(1); + + // {{content word="0"}} + output.results.fail['GS001-DEPR-C0H'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-C0H'].failures.length.should.eql(2); + + // css class .page-template-{slug} + output.results.fail['GS001-DEPR-CSS-PATS'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CSS-PATS'].failures.length.should.eql(2); + + // css class .achive-template + output.results.fail['GS001-DEPR-CSS-AT'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CSS-AT'].failures.length.should.eql(1); + + // css class .kg-card-markdown + output.results.fail['GS001-DEPR-CSS-KGMD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CSS-KGMD'].failures.length.should.eql(5); + + // {{#get "posts" include="author"}} + output.results.fail['GS001-DEPR-AUTH-INCL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-INCL'].failures.length.should.eql(1); + + // {{#get "posts" fields="author"}} + output.results.fail['GS001-DEPR-AUTH-FIELD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-FIELD'].failures.length.should.eql(1); + + // {{#get "posts" filter="author:[...]"}} + output.results.fail['GS001-DEPR-AUTH-FILT'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-FILT'].failures.length.should.eql(1); + + // {{#author}} but not in author.hbs + output.results.fail['GS001-DEPR-AUTHBL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTHBL'].failures.length.should.eql(1); + + // {{#if author}} or {{#if author.*}} + output.results.fail['GS001-DEPR-CON-AUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-AUTH'].failures.length.should.eql(3); + + // {{#if post.author}} or {{#if post.author.*}} + output.results.fail['GS001-DEPR-CON-PAUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-PAUTH'].failures.length.should.eql(1); + + // {{author}} + output.results.fail['GS001-DEPR-AUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH'].failures.length.should.eql(1); + + // {{author.id}} + output.results.fail['GS001-DEPR-AUTH-ID'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-ID'].failures.length.should.eql(1); + + // {{author.slug}} + output.results.fail['GS001-DEPR-AUTH-SLUG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-SLUG'].failures.length.should.eql(2); + + // {{author.email}} + output.results.fail['GS001-DEPR-AUTH-MAIL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-MAIL'].failures.length.should.eql(1); + + // {{author.meta_title}} + output.results.fail['GS001-DEPR-AUTH-MT'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-MT'].failures.length.should.eql(1); + + // {{author.meta_description}} + output.results.fail['GS001-DEPR-AUTH-MD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-MD'].failures.length.should.eql(1); + + // {{author.name}} + output.results.fail['GS001-DEPR-AUTH-NAME'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-NAME'].failures.length.should.eql(1); + + // {{author.bio}} + output.results.fail['GS001-DEPR-AUTH-BIO'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-BIO'].failures.length.should.eql(1); + + // {{author.location}} + output.results.fail['GS001-DEPR-AUTH-LOC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-LOC'].failures.length.should.eql(1); + + // {{author.website}} + output.results.fail['GS001-DEPR-AUTH-WEB'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-WEB'].failures.length.should.eql(1); + + // {{author.twitter}} + output.results.fail['GS001-DEPR-AUTH-TW'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-TW'].failures.length.should.eql(1); + + // {{author.facebook}} + output.results.fail['GS001-DEPR-AUTH-FB'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-FB'].failures.length.should.eql(1); + + // {{author.profile_image}} + output.results.fail['GS001-DEPR-AUTH-PIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-PIMG'].failures.length.should.eql(1); + + // {{author.cover_image}} + output.results.fail['GS001-DEPR-AUTH-CIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-CIMG'].failures.length.should.eql(1); + + // {{author.url}} + output.results.fail['GS001-DEPR-AUTH-URL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-URL'].failures.length.should.eql(1); + + // {{post.author}} + output.results.fail['GS001-DEPR-PAUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH'].failures.length.should.eql(1); + + // {{post.author.id}} + output.results.fail['GS001-DEPR-PAUTH-ID'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-ID'].failures.length.should.eql(1); + + // {{post.author.slug}} + output.results.fail['GS001-DEPR-PAUTH-SLUG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-SLUG'].failures.length.should.eql(1); + + // {{post.author.email}} + output.results.fail['GS001-DEPR-PAUTH-MAIL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-MAIL'].failures.length.should.eql(1); + + // {{post.author.meta_title}} + output.results.fail['GS001-DEPR-PAUTH-MT'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-MT'].failures.length.should.eql(1); + + // {{post.author.meta_description}} + output.results.fail['GS001-DEPR-PAUTH-MD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-MD'].failures.length.should.eql(1); + + // {{post.author.name}} + output.results.fail['GS001-DEPR-PAUTH-NAME'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-NAME'].failures.length.should.eql(1); + + // {{post.author.bio}} + output.results.fail['GS001-DEPR-PAUTH-BIO'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-BIO'].failures.length.should.eql(1); + + // {{post.author.location}} + output.results.fail['GS001-DEPR-PAUTH-LOC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-LOC'].failures.length.should.eql(1); + + // {{post.author.website}} + output.results.fail['GS001-DEPR-PAUTH-WEB'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-WEB'].failures.length.should.eql(1); + + // {{post.author.twitter}} + output.results.fail['GS001-DEPR-PAUTH-TW'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-TW'].failures.length.should.eql(1); + + // {{post.author.facebook}} + output.results.fail['GS001-DEPR-PAUTH-FB'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-FB'].failures.length.should.eql(1); + + // {{post.author.profile_image}} + output.results.fail['GS001-DEPR-PAUTH-PIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-PIMG'].failures.length.should.eql(1); + + // {{post.author.cover_image}} + output.results.fail['GS001-DEPR-PAUTH-CIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-CIMG'].failures.length.should.eql(1); + + // {{post.author.url}} + output.results.fail['GS001-DEPR-PAUTH-URL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-URL'].failures.length.should.eql(1); + + // {{post.author_id}} + output.results.fail['GS001-DEPR-PAID'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAID'].failures.length.should.eql(1); + + // {{#../author}}, {{../author}}, {{#if../author}} + // {{#../author.*}}, {{../author.*}}, {{#if../author.*}} + output.results.fail['GS001-DEPR-NAUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-NAUTH'].failures.length.should.eql(1); + + // {{img_url author.*}} + output.results.fail['GS001-DEPR-IUA'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-IUA'].failures.length.should.eql(1); + + // {{error.statusCode}} + output.results.fail['GS001-DEPR-ESC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-ESC'].failures.length.should.eql(2); + + // {{@blog}} + output.results.fail['GS001-DEPR-BLOG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-BLOG'].failures.length.should.eql(2); + + // {{@blog.permalinks}} + output.results.fail['GS001-DEPR-BPL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-BPL'].failures.length.should.eql(1); + + // {{@site.ghost_head}} + output.results.fail['GS001-DEPR-SGH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-SGH'].failures.length.should.eql(1); + + // {{@site.ghost_foot}} + output.results.fail['GS001-DEPR-SGF'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-SGF'].failures.length.should.eql(1); + + // {{lang}} + output.results.fail['GS001-DEPR-BPL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-BPL'].failures.length.should.eql(1); + + // {{#get "users"}} + output.results.fail['GS001-DEPR-USER-GET'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-USER-GET'].failures.length.should.eql(1); + + // {{#each}} helper usage warning + output.results.fail['GS001-DEPR-EACH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-EACH'].failures.length.should.eql(1); + + // there are some single author rules which are not invalid for this theme. + output.results.pass.length.should.eql(17); + + done(); + }).catch(done); + }); + + it('[failure] theme is invalid', function (done) { + utils.testCheck(thisCheck, '001-deprecations/v4/invalid', options).then(function (output) { + output.should.be.a.ValidThemeObject(); + + output.results.fail.should.be.an.Object().with.keys( + 'GS001-DEPR-CSS-KGMD', + 'GS001-DEPR-AUTH-INCL', + 'GS001-DEPR-AUTH-FIELD', + 'GS001-DEPR-AUTH-FILT', + 'GS001-DEPR-AUTHBL', + 'GS001-DEPR-CON-AUTH', + 'GS001-DEPR-CON-PAUTH', + 'GS001-DEPR-AUTH', + 'GS001-DEPR-AUTH-ID', + 'GS001-DEPR-AUTH-SLUG', + 'GS001-DEPR-AUTH-MAIL', + 'GS001-DEPR-AUTH-MT', + 'GS001-DEPR-AUTH-MD', + 'GS001-DEPR-AUTH-NAME', + 'GS001-DEPR-AUTH-BIO', + 'GS001-DEPR-AUTH-LOC', + 'GS001-DEPR-AUTH-WEB', + 'GS001-DEPR-AUTH-TW', + 'GS001-DEPR-AUTH-FB', + 'GS001-DEPR-AUTH-PIMG', + 'GS001-DEPR-AUTH-CIMG', + 'GS001-DEPR-AUTH-URL', + 'GS001-DEPR-PAUTH', + 'GS001-DEPR-PAUTH-ID', + 'GS001-DEPR-PAUTH-SLUG', + 'GS001-DEPR-PAUTH-MAIL', + 'GS001-DEPR-PAUTH-MT', + 'GS001-DEPR-PAUTH-MD', + 'GS001-DEPR-PAUTH-NAME', + 'GS001-DEPR-PAUTH-BIO', + 'GS001-DEPR-PAUTH-LOC', + 'GS001-DEPR-PAUTH-WEB', + 'GS001-DEPR-PAUTH-TW', + 'GS001-DEPR-PAUTH-FB', + 'GS001-DEPR-PAUTH-PIMG', + 'GS001-DEPR-PAUTH-CIMG', + 'GS001-DEPR-PAUTH-URL', + 'GS001-DEPR-NAUTH', + 'GS001-DEPR-IUA', + 'GS001-DEPR-AIMG-2', + 'GS001-DEPR-ESC', + 'GS001-DEPR-BLOG', + 'GS001-DEPR-BPL', + 'GS001-DEPR-SPL', + 'GS001-DEPR-LANG', + 'GS001-DEPR-EACH' + ); + + // css class .kg-card-markdown + output.results.fail['GS001-DEPR-CSS-KGMD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CSS-KGMD'].failures.length.should.eql(1); + + // {{#get "posts" include="author"}} + output.results.fail['GS001-DEPR-AUTH-INCL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-INCL'].failures.length.should.eql(1); + + // {{#get "posts" fields="author"}} + output.results.fail['GS001-DEPR-AUTH-FIELD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-FIELD'].failures.length.should.eql(1); + + // {{#get "posts" filter="author:[...]"}} + output.results.fail['GS001-DEPR-AUTH-FILT'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-FILT'].failures.length.should.eql(1); + + // {{#author}} but not in author.hbs + output.results.fail['GS001-DEPR-AUTHBL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTHBL'].failures.length.should.eql(1); + + // {{#if author}} or {{#if author.*}} + output.results.fail['GS001-DEPR-CON-AUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-AUTH'].failures.length.should.eql(3); + + // {{#if post.author}} or {{#if post.author.*}} + output.results.fail['GS001-DEPR-CON-PAUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-CON-PAUTH'].failures.length.should.eql(1); + + // {{author}} + output.results.fail['GS001-DEPR-AUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH'].failures.length.should.eql(1); + + // {{author.id}} + output.results.fail['GS001-DEPR-AUTH-ID'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-ID'].failures.length.should.eql(1); + + // {{author.slug}} + output.results.fail['GS001-DEPR-AUTH-SLUG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-SLUG'].failures.length.should.eql(2); + + // {{author.email}} + output.results.fail['GS001-DEPR-AUTH-MAIL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-MAIL'].failures.length.should.eql(1); + + // {{author.meta_title}} + output.results.fail['GS001-DEPR-AUTH-MT'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-MT'].failures.length.should.eql(1); + + // {{author.meta_description}} + output.results.fail['GS001-DEPR-AUTH-MD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-MD'].failures.length.should.eql(1); + + // {{author.name}} + output.results.fail['GS001-DEPR-AUTH-NAME'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-NAME'].failures.length.should.eql(1); + + // {{author.bio}} + output.results.fail['GS001-DEPR-AUTH-BIO'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-BIO'].failures.length.should.eql(1); + + // {{author.location}} + output.results.fail['GS001-DEPR-AUTH-LOC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-LOC'].failures.length.should.eql(1); + + // {{author.website}} + output.results.fail['GS001-DEPR-AUTH-WEB'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-WEB'].failures.length.should.eql(1); + + // {{author.twitter}} + output.results.fail['GS001-DEPR-AUTH-TW'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-TW'].failures.length.should.eql(1); + + // {{author.facebook}} + output.results.fail['GS001-DEPR-AUTH-FB'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-FB'].failures.length.should.eql(1); + + // {{author.profile_image}} + output.results.fail['GS001-DEPR-AUTH-PIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-PIMG'].failures.length.should.eql(1); + + // {{author.cover_image}} + output.results.fail['GS001-DEPR-AUTH-CIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-CIMG'].failures.length.should.eql(1); + + // {{author.url}} + output.results.fail['GS001-DEPR-AUTH-URL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-URL'].failures.length.should.eql(1); + + // {{post.author}} + output.results.fail['GS001-DEPR-PAUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH'].failures.length.should.eql(1); + + // {{post.author.id}} + output.results.fail['GS001-DEPR-PAUTH-ID'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-ID'].failures.length.should.eql(1); + + // {{post.author.slug}} + output.results.fail['GS001-DEPR-PAUTH-SLUG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-SLUG'].failures.length.should.eql(1); + + // {{post.author.email}} + output.results.fail['GS001-DEPR-PAUTH-MAIL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-MAIL'].failures.length.should.eql(1); + + // {{post.author.meta_title}} + output.results.fail['GS001-DEPR-PAUTH-MT'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-MT'].failures.length.should.eql(1); + + // {{post.author.meta_description}} + output.results.fail['GS001-DEPR-PAUTH-MD'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-MD'].failures.length.should.eql(1); + + // {{post.author.name}} + output.results.fail['GS001-DEPR-PAUTH-NAME'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-NAME'].failures.length.should.eql(1); + + // {{post.author.bio}} + output.results.fail['GS001-DEPR-PAUTH-BIO'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-BIO'].failures.length.should.eql(1); + + // {{post.author.location}} + output.results.fail['GS001-DEPR-PAUTH-LOC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-LOC'].failures.length.should.eql(1); + + // {{post.author.website}} + output.results.fail['GS001-DEPR-PAUTH-WEB'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-WEB'].failures.length.should.eql(1); + + // {{post.author.twitter}} + output.results.fail['GS001-DEPR-PAUTH-TW'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-TW'].failures.length.should.eql(1); + + // {{post.author.facebook}} + output.results.fail['GS001-DEPR-PAUTH-FB'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-FB'].failures.length.should.eql(1); + + // {{post.author.profile_image}} + output.results.fail['GS001-DEPR-PAUTH-PIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-PIMG'].failures.length.should.eql(1); + + // {{post.author.cover_image}} + output.results.fail['GS001-DEPR-PAUTH-CIMG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-CIMG'].failures.length.should.eql(1); + + // {{post.author.url}} + output.results.fail['GS001-DEPR-PAUTH-URL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PAUTH-URL'].failures.length.should.eql(1); + + // {{#../author}}, {{../author}}, {{#if../author}} + // {{#../author.*}}, {{../author.*}}, {{#if../author.*}} + output.results.fail['GS001-DEPR-NAUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-NAUTH'].failures.length.should.eql(1); + + // {{img_url author.*}} + output.results.fail['GS001-DEPR-IUA'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-IUA'].failures.length.should.eql(1); + + // {{primary_author.image}} + output.results.fail['GS001-DEPR-AIMG-2'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AIMG-2'].failures.length.should.eql(1); + + // {{error.statusCode}} + output.results.fail['GS001-DEPR-ESC'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-ESC'].failures.length.should.eql(2); + + // {{@blog.*}} + output.results.fail['GS001-DEPR-BLOG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-BLOG'].failures.length.should.eql(1); + + // {{@blog.permalinks}} + output.results.fail['GS001-DEPR-BPL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-BPL'].failures.length.should.eql(1); + + // {{@site.permalinks}} + output.results.fail['GS001-DEPR-SPL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-SPL'].failures.length.should.eql(1); + + // {{lang}} + output.results.fail['GS001-DEPR-LANG'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-LANG'].failures.length.should.eql(1); + + // {{#each}} helper usage warning + output.results.fail['GS001-DEPR-EACH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-EACH'].failures.length.should.eql(1); + + output.results.pass.should.be.an.Array().with.lengthOf(46); + + done(); + }).catch(done); + }); + + it('[success] should show no error if no deprecated helpers used', function (done) { + utils.testCheck(thisCheck, '001-deprecations/v4/valid', options).then(function (output) { + output.should.be.a.ValidThemeObject(); + + output.results.fail.should.be.an.Object().which.is.empty(); + output.results.pass.should.be.an.Array().with.lengthOf(92); + + done(); + }).catch(done); + }); + + it('[mixed] should pass and fail when some rules pass and others fail', function (done) { + utils.testCheck(thisCheck, '001-deprecations/v4/mixed', options).then(function (output) { + output.should.be.a.ValidThemeObject(); + + output.results.fail.should.be.an.Object().with.keys( + 'GS001-DEPR-IMG', + 'GS001-DEPR-C0H', + 'GS001-DEPR-CSS-AT', + 'GS001-DEPR-CSS-PATS', + 'GS001-DEPR-CSS-KGMD', + 'GS001-DEPR-AUTH-INCL', + 'GS001-DEPR-AUTH-FIELD', + 'GS001-DEPR-AUTH-FILT', + 'GS001-DEPR-AUTH', + 'GS001-DEPR-CON-AUTH', + 'GS001-DEPR-CON-PAUTH', + 'GS001-DEPR-AUTH-ID', + 'GS001-DEPR-AUTH-SLUG', + 'GS001-DEPR-AUTH-MAIL', + 'GS001-DEPR-AUTH-MT', + 'GS001-DEPR-AUTH-MD', + 'GS001-DEPR-AUTH-NAME', + 'GS001-DEPR-AUTH-BIO', + 'GS001-DEPR-AUTH-LOC', + 'GS001-DEPR-AUTH-WEB', + 'GS001-DEPR-PAUTH', + 'GS001-DEPR-PAUTH-ID', + 'GS001-DEPR-PAUTH-ID', + 'GS001-DEPR-PAUTH-SLUG', + 'GS001-DEPR-PAUTH-MAIL', + 'GS001-DEPR-PAUTH-MT', + 'GS001-DEPR-PAUTH-MD', + 'GS001-DEPR-PAUTH-NAME', + 'GS001-DEPR-PAUTH-BIO', + 'GS001-DEPR-PAUTH-LOC', + 'GS001-DEPR-NAUTH', + 'GS001-DEPR-IUA', + 'GS001-DEPR-ESC', + 'GS001-DEPR-BPL', + 'GS001-DEPR-BLOG' + ); + + output.results.fail['GS001-DEPR-AUTH-INCL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH-INCL'].failures.length.should.eql(1); + + output.results.fail['GS001-DEPR-AUTH'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-AUTH'].failures.length.should.eql(1); + + output.results.pass.should.be.an.Array().with.lengthOf(58); + + done(); + }).catch(done); + }); + }); }); diff --git a/test/005-template-compile.test.js b/test/005-template-compile.test.js index 852a97d5..f41ae7f9 100644 --- a/test/005-template-compile.test.js +++ b/test/005-template-compile.test.js @@ -3,7 +3,10 @@ var should = require('should'), // eslint-disable-line no-unused-vars thisCheck = require('../lib/checks/005-template-compile'); describe('005 Template compile', function () { - const options = {checkVersion: 'v1'}; + // checks "latest" rules only + // NOTE: if any of the rules in versions become different should introduce + // similar test structure as in deprecations suite (describe group per version) + const options = {}; it('should output empty array for a theme with no templates', function (done) { utils.testCheck(thisCheck, 'is-empty', options).then(function (output) { diff --git a/test/010-package-json.test.js b/test/010-package-json.test.js index 0f963ffa..594beb30 100644 --- a/test/010-package-json.test.js +++ b/test/010-package-json.test.js @@ -368,4 +368,85 @@ describe('010 package.json', function () { }).catch(done); }); }); + + describe('v4:', function () { + const options = {checkVersion: 'v3'}; + + it('valid fields', function (done) { + utils.testCheck(thisCheck, '010-packagejson/fields-are-valid', options).then(function (theme) { + theme.should.be.a.ValidThemeObject(); + + theme.results.pass.should.eql([ + 'GS010-PJ-REQ', + 'GS010-PJ-PARSE', + 'GS010-PJ-NAME-REQ', + 'GS010-PJ-NAME-LC', + 'GS010-PJ-NAME-HY', + 'GS010-PJ-VERSION-SEM', + 'GS010-PJ-VERSION-REQ', + 'GS010-PJ-AUT-EM-VAL', + 'GS010-PJ-AUT-EM-REQ', + 'GS010-PJ-CONF-PPP', + 'GS010-PJ-CONF-PPP-INT', + 'GS010-PJ-KEYWORDS' + ]); + + theme.results.fail.should.be.an.Object().which.is.empty(); + done(); + }).catch(done); + }); + + it('invalid fields', function (done) { + utils.testCheck(thisCheck, '010-packagejson/fields-are-invalid', options).then(function (theme) { + theme.should.be.a.ValidThemeObject(); + + theme.results.pass.should.eql([ + 'GS010-PJ-REQ', + 'GS010-PJ-PARSE', + 'GS010-PJ-NAME-REQ', + 'GS010-PJ-VERSION-REQ', + 'GS010-PJ-AUT-EM-REQ', + 'GS010-PJ-CONF-PPP' + ]); + + theme.results.fail.should.be.an.Object().with.keys( + 'GS010-PJ-NAME-LC', + 'GS010-PJ-NAME-HY', + 'GS010-PJ-VERSION-SEM', + 'GS010-PJ-AUT-EM-VAL', + 'GS010-PJ-CONF-PPP-INT', + 'GS010-PJ-KEYWORDS' + ); + + theme.results.fail['GS010-PJ-NAME-LC'].failures[0].ref.should.eql('package.json'); + + done(); + }).catch(done); + }); + + it('missing fields', function (done) { + utils.testCheck(thisCheck, '010-packagejson/fields-are-missing', options).then(function (theme) { + theme.should.be.a.ValidThemeObject(); + + theme.results.pass.should.eql([ + 'GS010-PJ-REQ', + 'GS010-PJ-PARSE' + ]); + + theme.results.fail.should.be.an.Object().with.keys( + 'GS010-PJ-AUT-EM-REQ', + 'GS010-PJ-NAME-REQ', + 'GS010-PJ-VERSION-REQ', + 'GS010-PJ-NAME-LC', + 'GS010-PJ-NAME-HY', + 'GS010-PJ-VERSION-SEM', + 'GS010-PJ-CONF-PPP', + 'GS010-PJ-AUT-EM-VAL', + 'GS010-PJ-KEYWORDS' + ); + + done(); + }).catch(done); + }); + }); }); diff --git a/test/020-theme-structure.test.js b/test/020-theme-structure.test.js index ee316ddd..56ae91dd 100644 --- a/test/020-theme-structure.test.js +++ b/test/020-theme-structure.test.js @@ -4,7 +4,10 @@ var should = require('should'), // eslint-disable-line no-unused-vars thisCheck = require('../lib/checks/020-theme-structure'); describe('020 Theme structure', function () { - const options = {checkVersion: 'v1'}; + // checks "latest" rules only + // NOTE: if any of the rules in versions become different should introduce + // similar test structure as in deprecations suite (describe group per version) + const options = {}; it('should fail all rules if no files present', function (done) { utils.testCheck(thisCheck, 'is-empty', options).then(function (output) { diff --git a/test/030-assets.test.js b/test/030-assets.test.js index 1fac1245..7296cb71 100644 --- a/test/030-assets.test.js +++ b/test/030-assets.test.js @@ -3,7 +3,10 @@ var should = require('should'), // eslint-disable-line no-unused-vars thisCheck = require('../lib/checks/030-assets'); describe('030 Assets', function () { - const options = {checkVersion: 'v1'}; + // checks "latest" rules only + // NOTE: if any of the rules in versions become different should introduce + // similar test structure as in deprecations suite (describe group per version) + const options = {}; it('should show a warning for missing asset helper when an asset is detected', function (done) { utils.testCheck(thisCheck, '030-assets/missing', options).then(function (output) { diff --git a/test/040-ghost-head-foot.test.js b/test/040-ghost-head-foot.test.js index 52d91493..a8d858c4 100644 --- a/test/040-ghost-head-foot.test.js +++ b/test/040-ghost-head-foot.test.js @@ -3,6 +3,9 @@ const utils = require('./utils'); const thisCheck = require('../lib/checks/040-ghost-head-foot'); describe('040 Ghost head & foot', function () { + // checks "latest" rules only + // NOTE: if any of the rules in versions become different should introduce + // similar test structure as in deprecations suite (describe group per version) const options = {}; it('should show warnings for missing ghost head & foot helpers when no .hbs files are present', function (done) { diff --git a/test/050-koenig-css-classes.test.js b/test/050-koenig-css-classes.test.js index e4919da6..7a0018e9 100644 --- a/test/050-koenig-css-classes.test.js +++ b/test/050-koenig-css-classes.test.js @@ -175,4 +175,84 @@ describe('050 Koenig CSS classes', function () { }).catch(done); }); }); + + describe('v4:', function () { + const options = {checkVersion: 'v4'}; + + it('[failure] should invalidate theme when .css file is missing', function (done) { + utils.testCheck(thisCheck, 'is-empty', options).then(function (output) { + output.should.be.a.ValidThemeObject(); + + output.results.pass.should.be.an.Array().which.is.empty(); + + output.results.fail.should.be.an.Object().with.keys('GS050-CSS-KGWW', 'GS050-CSS-KGWF', 'GS050-CSS-KGGC', 'GS050-CSS-KGGR', 'GS050-CSS-KGGI'); + + output.results.fail['GS050-CSS-KGWW'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGWF'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGGC'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGGR'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGGI'].should.be.a.ValidFailObject(); + + output.results.fail['GS050-CSS-KGWF'].failures.length.should.eql(1); + output.results.fail['GS050-CSS-KGWW'].failures.length.should.eql(1); + output.results.fail['GS050-CSS-KGGC'].failures.length.should.eql(1); + output.results.fail['GS050-CSS-KGGR'].failures.length.should.eql(1); + output.results.fail['GS050-CSS-KGGI'].failures.length.should.eql(1); + + output.results.fail['GS050-CSS-KGWF'].failures[0].ref.should.eql('styles'); + output.results.fail['GS050-CSS-KGWW'].failures[0].ref.should.eql('styles'); + output.results.fail['GS050-CSS-KGGC'].failures[0].ref.should.eql('styles'); + output.results.fail['GS050-CSS-KGGR'].failures[0].ref.should.eql('styles'); + output.results.fail['GS050-CSS-KGGI'].failures[0].ref.should.eql('styles'); + + done(); + }).catch(done); + }); + + it('[failure] should invalidate theme when CSS classes are missing', function (done) { + utils.testCheck(thisCheck, '050-koenig-css-classes/missing', options).then(function (output) { + output.should.be.a.ValidThemeObject(); + + output.results.pass.should.be.an.Array().which.is.empty(); + + output.results.fail.should.be.an.Object().with.keys('GS050-CSS-KGWW', 'GS050-CSS-KGWF', 'GS050-CSS-KGGC', 'GS050-CSS-KGGR', 'GS050-CSS-KGGI'); + + output.results.fail['GS050-CSS-KGWW'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGWF'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGGC'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGGR'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGGI'].should.be.a.ValidFailObject(); + + done(); + }).catch(done); + }); + + it('[failure] should invalidate theme when three CSS classes are missing (classes are spread in hbs and css files)', function (done) { + utils.testCheck(thisCheck, '050-koenig-css-classes/mixed', options).then(function (output) { + output.should.be.a.ValidThemeObject(); + + output.results.pass.should.be.an.Array().with.lengthOf(2); + + output.results.fail.should.be.an.Object().with.keys('GS050-CSS-KGWF', 'GS050-CSS-KGGC', 'GS050-CSS-KGGI'); + + output.results.fail['GS050-CSS-KGWF'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGGC'].should.be.a.ValidFailObject(); + output.results.fail['GS050-CSS-KGGI'].should.be.a.ValidFailObject(); + + done(); + }).catch(done); + }); + + it('[success] should pass theme when CSS classes are present', function (done) { + utils.testCheck(thisCheck, '050-koenig-css-classes/valid', options).then(function (output) { + output.should.be.a.ValidThemeObject(); + + output.results.pass.should.be.an.Array().with.lengthOf(5); + + output.results.fail.should.be.an.Object().which.is.empty(); + + done(); + }).catch(done); + }); + }); }); diff --git a/test/fixtures/themes/001-deprecations/v4/invalid/assets/my.css b/test/fixtures/themes/001-deprecations/v4/invalid/assets/my.css new file mode 100644 index 00000000..9dc0e8ca --- /dev/null +++ b/test/fixtures/themes/001-deprecations/v4/invalid/assets/my.css @@ -0,0 +1 @@ +.kg-card-markdown {} diff --git a/test/fixtures/themes/001-deprecations/v4/invalid/author.hbs b/test/fixtures/themes/001-deprecations/v4/invalid/author.hbs new file mode 100644 index 00000000..db30d591 --- /dev/null +++ b/test/fixtures/themes/001-deprecations/v4/invalid/author.hbs @@ -0,0 +1,8 @@ +{{#author}} + {{location}} +{{/author}} + +{{#is author}}{{/is}} + +{{#if author}}{{/if}} +{{#if author.email}}{{/if}} \ No newline at end of file diff --git a/test/fixtures/themes/001-deprecations/v4/invalid/default.hbs b/test/fixtures/themes/001-deprecations/v4/invalid/default.hbs new file mode 100644 index 00000000..e0ef51cf --- /dev/null +++ b/test/fixtures/themes/001-deprecations/v4/invalid/default.hbs @@ -0,0 +1,31 @@ + + + + diff --git a/bin/cli.js b/bin/cli.js index 7ffd77b4..5887752e 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -57,6 +57,8 @@ prettyCLI options.checkVersion = 'v2'; } else if (argv.v3) { options.checkVersion = 'v3'; + } else if (argv.v4) { + options.checkVersion = 'v4'; } else if (argv.canary) { options.checkVersion = 'canary'; } else { diff --git a/lib/checker.js b/lib/checker.js index 250e6cfc..6b1edcaa 100644 --- a/lib/checker.js +++ b/lib/checker.js @@ -18,13 +18,13 @@ const checks = requireDir('./checks'); const checker = function checkAll(themePath, options) { options = options || {}; - const passedVersion = _.get(options, 'checkVersion', 'v2'); + const passedVersion = _.get(options, 'checkVersion', 'v3'); let version = passedVersion; if (passedVersion === 'latest') { - version = 'v2'; - } else if (passedVersion === 'canary') { version = 'v3'; + } else if (passedVersion === 'canary') { + version = 'v4'; } return readTheme(themePath) diff --git a/lib/specs/index.js b/lib/specs/index.js index e4e10611..74be5c94 100644 --- a/lib/specs/index.js +++ b/lib/specs/index.js @@ -5,9 +5,9 @@ module.exports = { let [version] = key; if (version === 'latest') { - version = 'v2'; - } else if (version === 'canary') { version = 'v3'; + } else if (version === 'canary') { + version = 'v4'; } debug('Checking against version: ', version); diff --git a/lib/specs/v4.js b/lib/specs/v4.js new file mode 100644 index 00000000..3ef75550 --- /dev/null +++ b/lib/specs/v4.js @@ -0,0 +1,34 @@ +const _ = require('lodash'); +const previousSpec = require('./v3'); +const ghostVersions = require('../utils').versions; +const docsBaseUrl = `https://ghost.org/docs/api/handlebars-themes/`; +const prevDocsBaseUrl = `https://themes.ghost.org/v${ghostVersions.v3.docs}/docs/`; +const prevDocsBaseUrlRegEx = new RegExp(prevDocsBaseUrl, 'g'); + +const previousKnownHelpers = previousSpec.knownHelpers; +const previousTemplates = previousSpec.templates; +const previousRules = previousSpec.rules; + +// assign new or overwrite existing knownHelpers, templates, or rules here: +let knownHelpers = []; +let templates = []; +let rules = { + // New rules +}; + +knownHelpers = _.union(previousKnownHelpers, knownHelpers); +templates = _.union(previousTemplates, templates); + +// Merge the previous rules into the new rules, but overwrite any specified property, +// as well as adding any new rule to the spec. +// Furthermore, replace the usage of the old doc URLs that we're linking to, with the +// new version. +rules = _.each(_.merge({}, previousRules, rules), function replaceDocsUrl(value) { + value.details = value.details.replace(prevDocsBaseUrlRegEx, docsBaseUrl); +}); + +module.exports = { + knownHelpers: knownHelpers, + templates: templates, + rules: rules +}; diff --git a/lib/utils/versions.json b/lib/utils/versions.json index ee5e0a72..49ff749a 100644 --- a/lib/utils/versions.json +++ b/lib/utils/versions.json @@ -1,14 +1,18 @@ { - "v1": { - "major": "1.x", - "docs": "1.25.0" - }, - "v2": { - "major": "2.x", - "docs": "2.1.0" - }, - "v3": { - "major": "3.x", - "docs": "3.0.0" + "v1": { + "major": "1.x", + "docs": "1.25.0" + }, + "v2": { + "major": "2.x", + "docs": "2.1.0" + }, + "v3": { + "major": "3.x", + "docs": "3.0.0" + }, + "v4": { + "major": "4.x", + "docs": "4.0.0" } } diff --git a/test/001-deprecations.test.js b/test/001-deprecations.test.js index 24b9a795..a297ac39 100644 --- a/test/001-deprecations.test.js +++ b/test/001-deprecations.test.js @@ -174,7 +174,7 @@ describe('001 Deprecations', function () { }); }); - describe('v2 version:', function () { + describe('v2:', function () { it('[failure] theme is completely invalid', function (done) { utils.testCheck(thisCheck, '001-deprecations/v2/invalid_all').then(function (output) { output.should.be.a.ValidThemeObject(); @@ -1537,4 +1537,687 @@ describe('001 Deprecations', function () { }).catch(done); }); }); + + describe('v4:', function () { + const options = {checkVersion: 'v4'}; + + it('[failure] theme is completely invalid', function (done) { + utils.testCheck(thisCheck, '001-deprecations/v4/invalid_all', options).then(function (output) { + output.should.be.a.ValidThemeObject(); + + output.results.fail.should.be.an.Object().with.keys( + 'GS001-DEPR-PURL', + 'GS001-DEPR-MD', + 'GS001-DEPR-IMG', + 'GS001-DEPR-COV', + 'GS001-DEPR-AIMG', + 'GS001-DEPR-PIMG', + 'GS001-DEPR-PAIMG', + 'GS001-DEPR-PAC', + 'GS001-DEPR-PTIMG', + 'GS001-DEPR-TSIMG', + 'GS001-DEPR-PPP', + 'GS001-DEPR-C0H', + 'GS001-DEPR-BC', + 'GS001-DEPR-CON-BC', + 'GS001-DEPR-AC', + 'GS001-DEPR-CON-AC', + 'GS001-DEPR-CON-AIMG', + 'GS001-DEPR-CON-PAC', + 'GS001-DEPR-CON-PAIMG', + 'GS001-DEPR-CON-PTIMG', + 'GS001-DEPR-CON-TSIMG', + 'GS001-DEPR-CON-IMG', + 'GS001-DEPR-CON-COV', + 'GS001-DEPR-CON-TIMG', + 'GS001-DEPR-TIMG', + 'GS001-DEPR-CSS-AT', + 'GS001-DEPR-CSS-PATS', + 'GS001-DEPR-CSS-KGMD', + 'GS001-DEPR-AUTH-INCL', + 'GS001-DEPR-AUTH-FIELD', + 'GS001-DEPR-AUTH-FILT', + 'GS001-DEPR-AUTHBL', + 'GS001-DEPR-CON-AUTH', + 'GS001-DEPR-CON-PAUTH', + 'GS001-DEPR-AUTH', + 'GS001-DEPR-AUTH-ID', + 'GS001-DEPR-AUTH-SLUG', + 'GS001-DEPR-AUTH-MAIL', + 'GS001-DEPR-AUTH-MT', + 'GS001-DEPR-AUTH-MD', + 'GS001-DEPR-AUTH-NAME', + 'GS001-DEPR-AUTH-BIO', + 'GS001-DEPR-AUTH-LOC', + 'GS001-DEPR-AUTH-WEB', + 'GS001-DEPR-AUTH-TW', + 'GS001-DEPR-AUTH-FB', + 'GS001-DEPR-AUTH-PIMG', + 'GS001-DEPR-AUTH-CIMG', + 'GS001-DEPR-AUTH-URL', + 'GS001-DEPR-PAUTH', + 'GS001-DEPR-PAUTH-ID', + 'GS001-DEPR-PAUTH-SLUG', + 'GS001-DEPR-PAUTH-MAIL', + 'GS001-DEPR-PAUTH-MT', + 'GS001-DEPR-PAUTH-MD', + 'GS001-DEPR-PAUTH-NAME', + 'GS001-DEPR-PAUTH-BIO', + 'GS001-DEPR-PAUTH-LOC', + 'GS001-DEPR-PAUTH-WEB', + 'GS001-DEPR-PAUTH-TW', + 'GS001-DEPR-PAUTH-FB', + 'GS001-DEPR-PAUTH-PIMG', + 'GS001-DEPR-PAUTH-CIMG', + 'GS001-DEPR-PAUTH-URL', + 'GS001-DEPR-NAUTH', + 'GS001-DEPR-IUA', + 'GS001-DEPR-ESC', + 'GS001-DEPR-BPL', + 'GS001-DEPR-SGH', + 'GS001-DEPR-SGF', + 'GS001-DEPR-BLOG', + 'GS001-DEPR-LANG', + 'GS001-DEPR-PAID', + 'GS001-DEPR-USER-GET', + 'GS001-DEPR-EACH' + ); + + // pageUrl + output.results.fail['GS001-DEPR-PURL'].should.be.a.ValidFailObject(); + output.results.fail['GS001-DEPR-PURL'].failures.length.should.eql(3); + + // meta_description in