2017-02-21 22:04:50 +03:00
/* jshint expr:true */
/* eslint-disable camelcase */
import Mirage from 'ember-cli-mirage' ;
2017-05-29 21:50:03 +03:00
import ctrlOrCmd from 'ghost-admin/utils/ctrl-or-cmd' ;
import destroyApp from '../../helpers/destroy-app' ;
2017-02-21 22:04:50 +03:00
import mockThemes from 'ghost-admin/mirage/config/themes' ;
2017-05-29 21:50:03 +03:00
import startApp from '../../helpers/start-app' ;
import { afterEach , beforeEach , describe , it } from 'mocha' ;
import { authenticateSession , invalidateSession } from 'ghost-admin/tests/helpers/ember-simple-auth' ;
import { expect } from 'chai' ;
2017-02-21 22:04:50 +03:00
describe ( 'Acceptance: Settings - Design' , function ( ) {
let application ;
beforeEach ( function ( ) {
application = startApp ( ) ;
} ) ;
afterEach ( function ( ) {
destroyApp ( application ) ;
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'redirects to signin when not authenticated' , async function ( ) {
2017-02-21 22:04:50 +03:00
invalidateSession ( application ) ;
2017-04-24 15:29:48 +03:00
await visit ( '/settings/design' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect ( currentURL ( ) , 'currentURL' ) . to . equal ( '/signin' ) ;
2017-02-21 22:04:50 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'redirects to team page when authenticated as author' , async function ( ) {
2017-02-21 22:04:50 +03:00
let role = server . create ( 'role' , { name : 'Author' } ) ;
server . create ( 'user' , { roles : [ role ] , slug : 'test-user' } ) ;
authenticateSession ( application ) ;
2017-04-24 15:29:48 +03:00
await visit ( '/settings/design' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect ( currentURL ( ) , 'currentURL' ) . to . equal ( '/team/test-user' ) ;
2017-02-21 22:04:50 +03:00
} ) ;
describe ( 'when logged in' , function ( ) {
beforeEach ( function ( ) {
let role = server . create ( 'role' , { name : 'Administrator' } ) ;
server . create ( 'user' , { roles : [ role ] } ) ;
authenticateSession ( application ) ;
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'can visit /settings/design' , async function ( ) {
await visit ( '/settings/design' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect ( currentPath ( ) ) . to . equal ( 'settings.design.index' ) ;
2017-08-11 18:28:05 +03:00
expect ( find ( '[data-test-save-button]' ) . text ( ) . trim ( ) , 'save button text' ) . to . equal ( 'Save' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
// fixtures contain two nav items, check for three rows as we
// should have one extra that's blank
expect (
find ( '.gh-blognav-item' ) . length ,
'navigation items count'
) . to . equal ( 3 ) ;
2017-02-21 22:04:50 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'saves navigation settings' , async function ( ) {
await visit ( '/settings/design' ) ;
await fillIn ( '.gh-blognav-label:first input' , 'Test' ) ;
await fillIn ( '.gh-blognav-url:first input' , '/test' ) ;
await triggerEvent ( '.gh-blognav-url:first input' , 'blur' ) ;
2017-02-21 22:04:50 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-save-button]' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
let [ navSetting ] = server . db . settings . where ( { key : 'navigation' } ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect ( navSetting . value ) . to . equal ( '[{"label":"Test","url":"/test/"},{"label":"About","url":"/about"}]' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
// don't test against .error directly as it will pick up failed
// tests "pre.error" elements
expect ( find ( 'span.error' ) . length , 'error fields count' ) . to . equal ( 0 ) ;
expect ( find ( '.gh-alert' ) . length , 'alerts count' ) . to . equal ( 0 ) ;
expect ( find ( '.response:visible' ) . length , 'validation errors count' )
. to . equal ( 0 ) ;
2017-02-21 22:04:50 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'validates new item correctly on save' , async function ( ) {
await visit ( '/settings/design' ) ;
2017-02-21 22:04:50 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-save-button]' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-item' ) . length ,
'number of nav items after saving with blank new item'
) . to . equal ( 3 ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '.gh-blognav-label:last input' , 'Test' ) ;
await fillIn ( '.gh-blognav-url:last input' , 'http://invalid domain/' ) ;
await triggerEvent ( '.gh-blognav-url:last input' , 'blur' ) ;
2017-02-21 22:04:50 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-save-button]' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-item' ) . length ,
'number of nav items after saving with invalid new item'
) . to . equal ( 3 ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-item:last .error' ) . length ,
'number of invalid fields in new item'
) . to . equal ( 1 ) ;
2017-02-21 22:04:50 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'clears unsaved settings when navigating away' , async function ( ) {
await visit ( '/settings/design' ) ;
await fillIn ( '.gh-blognav-label:first input' , 'Test' ) ;
await triggerEvent ( '.gh-blognav-label:first input' , 'blur' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '.gh-blognav-label:first input' ) . val ( ) ) . to . equal ( 'Test' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
await visit ( '/settings/code-injection' ) ;
await visit ( '/settings/design' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '.gh-blognav-label:first input' ) . val ( ) ) . to . equal ( 'Home' ) ;
2017-02-21 22:04:50 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'can add and remove items' , async function ( ) {
await visit ( '/settings/design' ) ;
await click ( '.gh-blognav-add' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-label:last .response' ) . is ( ':visible' ) ,
'blank label has validation error'
) . to . be . true ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '.gh-blognav-label:last input' , 'New' ) ;
await triggerEvent ( '.gh-blognav-label:last input' , 'keypress' , { } ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-label:last .response' ) . is ( ':visible' ) ,
'label validation is visible after typing'
) . to . be . false ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '.gh-blognav-url:last input' , '/new' ) ;
await triggerEvent ( '.gh-blognav-url:last input' , 'keypress' , { } ) ;
await triggerEvent ( '.gh-blognav-url:last input' , 'blur' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-url:last .response' ) . is ( ':visible' ) ,
'url validation is visible after typing'
) . to . be . false ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-url:last input' ) . val ( )
) . to . equal ( ` ${ window . location . protocol } // ${ window . location . host } /new/ ` ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
await click ( '.gh-blognav-add' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-item' ) . length ,
'number of nav items after successful add'
) . to . equal ( 4 ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-label:last input' ) . val ( ) ,
'new item label value after successful add'
) . to . be . blank ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-url:last input' ) . val ( ) ,
'new item url value after successful add'
) . to . equal ( ` ${ window . location . protocol } // ${ window . location . host } / ` ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-item .response:visible' ) . length ,
'number or validation errors shown after successful add'
) . to . equal ( 0 ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
await click ( '.gh-blognav-item:first .gh-blognav-delete' ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( '.gh-blognav-item' ) . length ,
'number of nav items after successful remove'
) . to . equal ( 3 ) ;
2017-02-21 22:04:50 +03:00
2017-05-18 13:48:37 +03:00
// CMD-S shortcut works
await triggerEvent ( '.gh-app' , 'keydown' , {
keyCode : 83 , // s
metaKey : ctrlOrCmd === 'command' ,
ctrlKey : ctrlOrCmd === 'ctrl'
} ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
let [ navSetting ] = server . db . settings . where ( { key : 'navigation' } ) ;
2017-02-21 22:04:50 +03:00
2017-04-24 15:29:48 +03:00
expect ( navSetting . value ) . to . equal ( '[{"label":"About","url":"/about"},{"label":"New","url":"/new/"}]' ) ;
2017-02-21 22:04:50 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'allows management of themes' , async function ( ) {
2017-02-21 22:04:50 +03:00
// lists available themes + active theme is highlighted
// theme upload
// - displays modal
// - validates mime type
// - validates casper.zip
// - handles validation errors
// - handles upload and close
// - handles upload and activate
// - displays overwrite warning if theme already exists
// theme activation
// - switches theme
// theme deletion
// - displays modal
// - deletes theme and refreshes list
server . loadFixtures ( 'themes' ) ;
2017-04-24 15:29:48 +03:00
await visit ( '/settings/design' ) ;
2017-02-21 22:04:50 +03:00
// lists available themes (themes are specified in mirage/fixtures/settings)
2017-04-24 15:29:48 +03:00
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-id]' ) . length ,
2017-04-24 15:29:48 +03:00
'shows correct number of themes'
) . to . equal ( 3 ) ;
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-active="true"] [data-test-theme-title]' ) . text ( ) . trim ( ) ,
2017-04-24 15:29:48 +03:00
'Blog theme marked as active'
) . to . equal ( 'Blog (default)' ) ;
2017-02-21 22:04:50 +03:00
// theme upload displays modal
2017-08-11 18:28:05 +03:00
await click ( '[data-test-upload-theme-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
find ( '.fullscreen-modal .modal-content:contains("Upload a theme")' ) . length ,
'theme upload modal displayed after button click'
) . to . equal ( 1 ) ;
2017-02-21 22:04:50 +03:00
// cancelling theme upload closes modal
2017-08-11 18:28:05 +03:00
await click ( '.fullscreen-modal [data-test-close-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
find ( '.fullscreen-modal' ) . length === 0 ,
'upload theme modal is closed when cancelling'
) . to . be . true ;
2017-02-21 22:04:50 +03:00
// theme upload validates mime type
2017-08-11 18:28:05 +03:00
await click ( '[data-test-upload-theme-button]' ) ;
2017-04-24 15:29:48 +03:00
await fileUpload ( '.fullscreen-modal input[type="file"]' , [ 'test' ] , { type : 'text/csv' } ) ;
expect (
find ( '.fullscreen-modal .failed' ) . text ( ) ,
'validation error is shown for invalid mime type'
) . to . match ( /is not supported/ ) ;
2017-02-21 22:04:50 +03:00
// theme upload validates casper.zip
2017-08-11 18:28:05 +03:00
await click ( '[data-test-upload-try-again-button]' ) ;
2017-04-24 15:29:48 +03:00
await fileUpload ( '.fullscreen-modal input[type="file"]' , [ 'test' ] , { name : 'casper.zip' , type : 'application/zip' } ) ;
expect (
find ( '.fullscreen-modal .failed' ) . text ( ) ,
'validation error is shown when uploading casper.zip'
) . to . match ( /default Casper theme cannot be overwritten/ ) ;
2017-02-21 22:04:50 +03:00
// theme upload handles upload errors
2017-04-24 15:29:48 +03:00
server . post ( '/themes/upload/' , function ( ) {
return new Mirage . Response ( 422 , { } , {
errors : [ {
message : 'Invalid theme'
} ]
2017-02-21 22:04:50 +03:00
} ) ;
} ) ;
2017-08-11 18:28:05 +03:00
await click ( '[data-test-upload-try-again-button]' ) ;
2017-04-24 15:29:48 +03:00
await fileUpload ( '.fullscreen-modal input[type="file"]' , [ 'test' ] , { name : 'error.zip' , type : 'application/zip' } ) ;
expect (
find ( '.fullscreen-modal .failed' ) . text ( ) . trim ( ) ,
'validation error is passed through from server'
) . to . equal ( 'Invalid theme' ) ;
// reset to default mirage handlers
mockThemes ( server ) ;
2017-02-21 22:04:50 +03:00
// theme upload handles validation errors
2017-04-24 15:29:48 +03:00
server . post ( '/themes/upload/' , function ( ) {
return new Mirage . Response ( 422 , { } , {
errors : [
{
message : 'Theme is not compatible or contains errors.' ,
errorType : 'ThemeValidationError' ,
errorDetails : [
{
level : 'error' ,
2017-07-20 13:30:45 +03:00
rule : 'Assets such as CSS & JS must use the <code>{{asset}}</code> helper' ,
details : '<p>The listed files should be included using the <code>{{asset}}</code> helper.</p>' ,
2017-04-24 15:29:48 +03:00
failures : [
{
2017-07-20 13:30:45 +03:00
ref : '/assets/javascripts/ui.js'
2017-04-24 15:29:48 +03:00
}
]
} ,
{
level : 'error' ,
2017-07-20 13:30:45 +03:00
rule : 'Templates must contain valid Handlebars.' ,
2017-04-24 15:29:48 +03:00
failures : [
{
2017-07-20 13:30:45 +03:00
ref : 'index.hbs' ,
message : 'The partial index_meta could not be found'
} ,
{
ref : 'tag.hbs' ,
message : 'The partial index_meta could not be found'
2017-04-24 15:29:48 +03:00
}
]
}
]
}
]
2017-02-21 22:04:50 +03:00
} ) ;
} ) ;
2017-04-24 15:29:48 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-upload-try-again-button]' ) ;
2017-04-24 15:29:48 +03:00
await fileUpload ( '.fullscreen-modal input[type="file"]' , [ 'test' ] , { name : 'bad-theme.zip' , type : 'application/zip' } ) ;
expect (
find ( '.fullscreen-modal h1' ) . text ( ) . trim ( ) ,
'modal title after uploading invalid theme'
) . to . equal ( 'Invalid theme' ) ;
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-rule-text' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'top-level errors are displayed'
) . to . match ( /Templates must contain valid Handlebars/ ) ;
2017-08-11 18:28:05 +03:00
await click ( '[data-test-toggle-details]' ) ;
2017-07-20 13:30:45 +03:00
2017-04-24 15:29:48 +03:00
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-details' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'top-level errors do not escape HTML'
) . to . match ( /The listed files should be included using the {{asset}} helper/ ) ;
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-list ul li' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'individual failures are displayed'
2017-07-20 13:30:45 +03:00
) . to . match ( /\/assets\/javascripts\/ui\.js/ ) ;
2017-04-24 15:29:48 +03:00
// reset to default mirage handlers
mockThemes ( server ) ;
2017-08-11 18:28:05 +03:00
await click ( '.fullscreen-modal [data-test-try-again-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
find ( '.theme-validation-errors' ) . length ,
'"Try Again" resets form after theme validation error'
) . to . equal ( 0 ) ;
expect (
find ( '.gh-image-uploader' ) . length ,
'"Try Again" resets form after theme validation error'
) . to . equal ( 1 ) ;
expect (
find ( '.fullscreen-modal h1' ) . text ( ) . trim ( ) ,
'"Try Again" resets form after theme validation error'
) . to . equal ( 'Upload a theme' ) ;
2017-02-21 22:04:50 +03:00
// theme upload handles validation warnings
2017-04-24 15:29:48 +03:00
server . post ( '/themes/upload/' , function ( { themes } ) {
let theme = {
name : 'blackpalm' ,
package : {
name : 'BlackPalm' ,
version : '1.0.0'
}
} ;
themes . create ( theme ) ;
theme . warnings = [ {
level : 'warning' ,
rule : 'Assets such as CSS & JS must use the <code>{{asset}}</code> helper' ,
details : '<p>The listed files should be included using the <code>{{asset}}</code> helper. For more information, please see the <a href="http://themes.ghost.org/docs/asset">asset helper documentation</a>.</p>' ,
failures : [
{
ref : '/assets/dist/img/apple-touch-icon.png'
} ,
{
ref : '/assets/dist/img/favicon.ico'
} ,
{
ref : '/assets/dist/css/blackpalm.min.css'
} ,
{
ref : '/assets/dist/js/blackpalm.min.js'
2017-03-03 18:31:42 +03:00
}
2017-04-24 15:29:48 +03:00
] ,
code : 'GS030-ASSET-REQ'
} ] ;
return new Mirage . Response ( 200 , { } , {
themes : [ theme ]
2017-02-21 22:04:50 +03:00
} ) ;
} ) ;
2017-04-24 15:29:48 +03:00
await fileUpload ( '.fullscreen-modal input[type="file"]' , [ 'test' ] , { name : 'warning-theme.zip' , type : 'application/zip' } ) ;
expect (
find ( '.fullscreen-modal h1' ) . text ( ) . trim ( ) ,
'modal title after uploading theme with warnings'
2017-08-02 13:30:47 +03:00
) . to . equal ( 'Upload successful with warnings' ) ;
2017-04-24 15:29:48 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-toggle-details]' ) ;
2017-07-20 13:30:45 +03:00
2017-04-24 15:29:48 +03:00
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-details' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'top-level warnings are displayed'
) . to . match ( /The listed files should be included using the {{asset}} helper/ ) ;
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-list ul li' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'individual warning failures are displayed'
) . to . match ( /\/assets\/dist\/img\/apple-touch-icon\.png/ ) ;
// reset to default mirage handlers
mockThemes ( server ) ;
2017-08-11 18:28:05 +03:00
await click ( '.fullscreen-modal [data-test-close-button]' ) ;
2017-02-21 22:04:50 +03:00
// theme upload handles success then close
2017-08-11 18:28:05 +03:00
await click ( '[data-test-upload-theme-button]' ) ;
2017-04-24 15:29:48 +03:00
await fileUpload ( '.fullscreen-modal input[type="file"]' , [ 'test' ] , { name : 'theme-1.zip' , type : 'application/zip' } ) ;
expect (
find ( '.fullscreen-modal h1' ) . text ( ) . trim ( ) ,
'modal header after successful upload'
) . to . equal ( 'Upload successful!' ) ;
expect (
find ( '.modal-body' ) . text ( ) ,
'modal displays theme name after successful upload'
) . to . match ( /"Test 1 - 0\.1" uploaded successfully/ ) ;
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-id]' ) . length ,
2017-04-24 15:29:48 +03:00
'number of themes in list grows after upload'
) . to . equal ( 5 ) ;
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-active="true"] [data-test-theme-title]' ) . text ( ) . trim ( ) ,
2017-04-24 15:29:48 +03:00
'newly uploaded theme is not active'
) . to . equal ( 'Blog (default)' ) ;
2017-08-11 18:28:05 +03:00
await click ( '.fullscreen-modal [data-test-close-button]' ) ;
2017-02-21 22:04:50 +03:00
// theme upload handles success then activate
2017-08-11 18:28:05 +03:00
await click ( '[data-test-upload-theme-button]' ) ;
2017-04-24 15:29:48 +03:00
await fileUpload ( '.fullscreen-modal input[type="file"]' , [ 'test' ] , { name : 'theme-2.zip' , type : 'application/zip' } ) ;
2017-08-11 18:28:05 +03:00
await click ( '.fullscreen-modal [data-test-activate-now-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-id]' ) . length ,
2017-04-24 15:29:48 +03:00
'number of themes in list grows after upload and activate'
) . to . equal ( 6 ) ;
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-active="true"] [data-test-theme-title]' ) . text ( ) . trim ( ) ,
2017-04-24 15:29:48 +03:00
'newly uploaded+activated theme is active'
) . to . equal ( 'Test 2' ) ;
2017-02-21 22:04:50 +03:00
// theme activation switches active theme
2017-08-11 18:28:05 +03:00
await click ( '[data-test-theme-id="casper"] [data-test-theme-activate-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-id="test-2"] .apps-card-app' ) . hasClass ( 'theme-list-item--active' ) ,
2017-04-24 15:29:48 +03:00
'previously active theme is not active'
) . to . be . false ;
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-id="casper"] .apps-card-app' ) . hasClass ( 'theme-list-item--active' ) ,
2017-04-24 15:29:48 +03:00
'activated theme is active'
) . to . be . true ;
2017-02-21 22:04:50 +03:00
2017-03-14 16:54:58 +03:00
// theme activation shows errors
2017-04-24 15:29:48 +03:00
server . put ( 'themes/:theme/activate' , function ( ) {
return new Mirage . Response ( 422 , { } , {
errors : [
{
message : 'Theme is not compatible or contains errors.' ,
errorType : 'ThemeValidationError' ,
errorDetails : [
{
level : 'error' ,
2017-07-20 13:30:45 +03:00
rule : 'Assets such as CSS & JS must use the <code>{{asset}}</code> helper' ,
details : '<p>The listed files should be included using the <code>{{asset}}</code> helper.</p>' ,
2017-04-24 15:29:48 +03:00
failures : [
{
2017-07-20 13:30:45 +03:00
ref : '/assets/javascripts/ui.js'
2017-04-24 15:29:48 +03:00
}
]
} ,
{
level : 'error' ,
2017-07-20 13:30:45 +03:00
rule : 'Templates must contain valid Handlebars.' ,
2017-04-24 15:29:48 +03:00
failures : [
{
2017-07-20 13:30:45 +03:00
ref : 'index.hbs' ,
message : 'The partial index_meta could not be found'
} ,
{
ref : 'tag.hbs' ,
message : 'The partial index_meta could not be found'
2017-04-24 15:29:48 +03:00
}
]
}
]
}
]
2017-03-14 16:54:58 +03:00
} ) ;
} ) ;
2017-04-24 15:29:48 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-theme-id="test-2"] [data-test-theme-activate-button]' ) ;
2017-04-24 15:29:48 +03:00
2017-08-11 18:28:05 +03:00
expect ( find ( '[data-test-theme-warnings-modal]' ) ) . to . exist ;
2017-04-24 15:29:48 +03:00
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-warnings-title]' ) . text ( ) . trim ( ) ,
2017-04-24 15:29:48 +03:00
'modal title after activating invalid theme'
2017-06-22 20:19:01 +03:00
) . to . equal ( 'Activation failed' ) ;
2017-04-24 15:29:48 +03:00
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-warnings]' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'top-level errors are displayed in activation errors'
) . to . match ( /Templates must contain valid Handlebars/ ) ;
2017-08-11 18:28:05 +03:00
await click ( '[data-test-toggle-details]' ) ;
2017-07-20 13:30:45 +03:00
2017-04-24 15:29:48 +03:00
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-details' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'top-level errors do not escape HTML in activation errors'
) . to . match ( /The listed files should be included using the {{asset}} helper/ ) ;
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-list ul li' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'individual failures are displayed in activation errors'
2017-07-20 13:30:45 +03:00
) . to . match ( /\/assets\/javascripts\/ui\.js/ ) ;
2017-04-24 15:29:48 +03:00
// restore default mirage handlers
mockThemes ( server ) ;
2017-08-11 18:28:05 +03:00
await click ( '[data-test-modal-close-button]' ) ;
expect ( find ( '[data-test-theme-warnings-modal]' ) ) . to . not . exist ;
2017-03-14 16:54:58 +03:00
// theme activation shows warnings
2017-04-24 15:29:48 +03:00
server . put ( 'themes/:theme/activate' , function ( { themes } , { params } ) {
themes . all ( ) . update ( 'active' , false ) ;
let theme = themes . findBy ( { name : params . theme } ) . update ( { active : true } ) ;
theme . update ( { warnings : [ {
level : 'warning' ,
rule : 'Assets such as CSS & JS must use the <code>{{asset}}</code> helper' ,
details : '<p>The listed files should be included using the <code>{{asset}}</code> helper. For more information, please see the <a href="http://themes.ghost.org/docs/asset">asset helper documentation</a>.</p>' ,
failures : [
{
ref : '/assets/dist/img/apple-touch-icon.png'
} ,
{
ref : '/assets/dist/img/favicon.ico'
} ,
{
ref : '/assets/dist/css/blackpalm.min.css'
} ,
{
ref : '/assets/dist/js/blackpalm.min.js'
}
] ,
code : 'GS030-ASSET-REQ'
} ] } ) ;
return { themes : [ theme ] } ;
2017-03-14 16:54:58 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-theme-id="test-2"] [data-test-theme-activate-button]' ) ;
2017-04-24 15:29:48 +03:00
2017-08-11 18:28:05 +03:00
expect ( find ( '[data-test-theme-warnings-modal]' ) ) . to . exist ;
2017-04-24 15:29:48 +03:00
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-warnings-title]' ) . text ( ) . trim ( ) ,
2017-04-24 15:29:48 +03:00
'modal title after activating theme with warnings'
2017-08-02 13:30:47 +03:00
) . to . equal ( 'Activation successful with warnings' ) ;
2017-04-24 15:29:48 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-toggle-details]' ) ;
2017-07-20 13:30:45 +03:00
2017-04-24 15:29:48 +03:00
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-details' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'top-level warnings are displayed in activation warnings'
) . to . match ( /The listed files should be included using the {{asset}} helper/ ) ;
expect (
2017-07-20 13:30:45 +03:00
find ( '.theme-validation-list ul li' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'individual warning failures are displayed in activation warnings'
) . to . match ( /\/assets\/dist\/img\/apple-touch-icon\.png/ ) ;
// restore default mirage handlers
mockThemes ( server ) ;
2017-08-11 18:28:05 +03:00
await click ( '[data-test-modal-close-button]' ) ;
2017-03-14 16:54:58 +03:00
// reactivate casper to continue tests
2017-08-11 18:28:05 +03:00
await click ( '[data-test-theme-id="casper"] [data-test-theme-activate-button]' ) ;
2017-03-14 16:54:58 +03:00
2017-02-21 22:04:50 +03:00
// theme deletion displays modal
2017-08-11 18:28:05 +03:00
await click ( '[data-test-theme-id="test-1"] [data-test-theme-delete-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-delete-theme-modal]' ) . length ,
2017-04-24 15:29:48 +03:00
'theme deletion modal displayed after button click'
) . to . equal ( 1 ) ;
2017-02-21 22:04:50 +03:00
// cancelling theme deletion closes modal
2017-08-11 18:28:05 +03:00
await click ( '.fullscreen-modal [data-test-cancel-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
find ( '.fullscreen-modal' ) . length === 0 ,
'delete theme modal is closed when cancelling'
) . to . be . true ;
2017-02-21 22:04:50 +03:00
// confirming theme deletion closes modal and refreshes list
2017-08-11 18:28:05 +03:00
await click ( '[data-test-theme-id="test-1"] [data-test-theme-delete-button]' ) ;
await click ( '.fullscreen-modal [data-test-delete-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
find ( '.fullscreen-modal' ) . length === 0 ,
'delete theme modal closes after deletion'
) . to . be . true ;
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-id]' ) . length ,
2017-04-24 15:29:48 +03:00
'number of themes in list shrinks after delete'
) . to . equal ( 5 ) ;
expect (
2017-08-11 18:28:05 +03:00
find ( '[data-test-theme-title]' ) . text ( ) ,
2017-04-24 15:29:48 +03:00
'correct theme is removed from theme list after deletion'
) . to . not . match ( /Test 1/ ) ;
2017-02-21 22:04:50 +03:00
// validation errors are handled when deleting a theme
2017-04-24 15:29:48 +03:00
server . del ( '/themes/:theme/' , function ( ) {
return new Mirage . Response ( 422 , { } , {
errors : [ {
message : 'Can\'t delete theme'
} ]
2017-02-21 22:04:50 +03:00
} ) ;
} ) ;
2017-04-24 15:29:48 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-theme-id="test-2"] [data-test-theme-delete-button]' ) ;
await click ( '.fullscreen-modal [data-test-delete-button]' ) ;
2017-04-24 15:29:48 +03:00
expect (
find ( '.fullscreen-modal' ) . length === 0 ,
'delete theme modal closes after failed deletion'
) . to . be . true ;
expect (
find ( '.gh-alert' ) . length ,
'alert is shown when deletion fails'
) . to . equal ( 1 ) ;
expect (
find ( '.gh-alert' ) . text ( ) ,
'failed deletion alert has correct text'
) . to . match ( /Can't delete theme/ ) ;
// restore default mirage handlers
mockThemes ( server ) ;
2017-02-21 22:04:50 +03:00
} ) ;
2017-06-01 16:44:04 +03:00
it ( 'can delete then re-upload the same theme' , async function ( ) {
server . loadFixtures ( 'themes' ) ;
// mock theme upload to emulate uploading theme with same id
server . post ( '/themes/upload/' , function ( { themes } ) {
let theme = themes . create ( {
name : 'foo' ,
package : {
name : 'Foo' ,
version : '0.1'
}
} ) ;
return { themes : [ theme ] } ;
} ) ;
await visit ( '/settings/design' ) ;
2017-08-11 18:28:05 +03:00
await click ( '[data-test-theme-id="foo"] [data-test-theme-delete-button]' ) ;
await click ( '.fullscreen-modal [data-test-delete-button]' ) ;
2017-06-01 16:44:04 +03:00
2017-08-11 18:28:05 +03:00
await click ( '[data-test-upload-theme-button]' ) ;
2017-06-01 16:44:04 +03:00
await fileUpload ( '.fullscreen-modal input[type="file"]' , [ 'test' ] , { name : 'foo.zip' , type : 'application/zip' } ) ;
// this will fail if upload failed because there won't be an activate now button
2017-08-11 18:28:05 +03:00
await click ( '.fullscreen-modal [data-test-activate-now-button]' ) ;
2017-06-01 16:44:04 +03:00
} ) ;
2017-02-21 22:04:50 +03:00
} ) ;
} ) ;