├── .gitignore ├── docroot └── readme.md ├── drush ├── aliases │ └── example.aliases.drushrc.php ├── commands │ ├── build.drush.inc │ ├── casperjs │ │ ├── README.md │ │ ├── casperjs.drush.inc │ │ └── includes │ │ │ ├── common.js │ │ │ ├── post-test.js │ │ │ ├── pre-test.js │ │ │ └── session.js │ ├── downsync.drush.inc │ ├── policy.drush.inc │ └── registry_rebuild │ │ ├── LICENSE.txt │ │ ├── README.txt │ │ ├── registry_rebuild.drush.inc │ │ └── registry_rebuild.php ├── drushrc.php └── readme.md ├── patches └── readme.md ├── readme.md ├── results └── readme.md ├── scripts └── README.md └── tests ├── create_content.js ├── homepage.js └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Sensitive information # 2 | ######################### 3 | # Ignore configuration files that may contain sensitive information. 4 | docroot/sites/*/settings*.php 5 | *.local.php 6 | 7 | # User Generated Content # 8 | ########################## 9 | docroot/files 10 | docroot/sites/*/files 11 | docroot/sites/*/private 12 | 13 | # Vagrant Files # 14 | ################# 15 | .vagrant 16 | 17 | # Compiled source # 18 | ################### 19 | *.com 20 | *.class 21 | *.dll 22 | *.exe 23 | *.o 24 | *.so 25 | 26 | # Packages # 27 | ############ 28 | # It's better to unpack these files and commit the raw source, git has its own 29 | # built in compression methods 30 | *.7z 31 | *.dmg 32 | *.gz 33 | *.iso 34 | *.jar 35 | *.rar 36 | *.tar 37 | *.zip 38 | 39 | # Logs and databases # 40 | ###################### 41 | *.log 42 | *.sql 43 | *.sqlite 44 | 45 | # OS generated files # 46 | ###################### 47 | .DS_Store* 48 | ehthumbs.db 49 | Icon\? 50 | Thumbs.db 51 | -------------------------------------------------------------------------------- /docroot/readme.md: -------------------------------------------------------------------------------- 1 | This is the directory where Drupal core will be installed. 2 | 3 | Your web server should point to this directory as the root. 4 | -------------------------------------------------------------------------------- /drush/aliases/example.aliases.drushrc.php: -------------------------------------------------------------------------------- 1 | 'example.lan', 15 | 'root' => str_replace('drush/aliases', 'docroot', dirname(__FILE__)), 16 | ); 17 | 18 | $aliases['stage'] = array( 19 | 'uri' => 'stage.example.com', 20 | 'root' => '/var/www/stage.example.com/docroot', 21 | 'remote-host' => 'example.com', 22 | 'remote-user' => 'user', 23 | ); 24 | 25 | $aliases['live'] = array( 26 | 'uri' => 'example.com', 27 | 'root' => '/var/www/stage.example.com/docroot', 28 | 'remote-host' => 'example.com', 29 | 'remote-user' => 'user', 30 | ); 31 | -------------------------------------------------------------------------------- /drush/commands/build.drush.inc: -------------------------------------------------------------------------------- 1 | 'Runs database updates, reverts features and clears caches.', 16 | 'callback' => '_drush_build', 17 | 'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, 18 | ); 19 | 20 | $items['devify'] = array( 21 | 'description' => 'Configures the current database for development.', 22 | 'callback' => '_drush_devify', 23 | 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, 24 | 'options' => array( 25 | 'enable-modules' => 'A comma separated list of modules to enable.', 26 | 'disable-modules' => 'A comma separated list of modules to disable.', 27 | 'delete-variables' => 'A comma separated list of variables to delete.', 28 | 'reset-variables' => 'A comma separated list of variables to reset with ' . 29 | 'the format foo=var,hey=ho.', 30 | ), 31 | 'examples' => array( 32 | 'drush devify' => 'Uses command default values to set up a database for development.', 33 | 'drush devify --enable-modules=xhprof,devel' => 'Enables XHProf and Devel modules', 34 | 'drush devify --reset-variables=site_mail=local@local.com,file_temporary_path=/tmp' 35 | => 'Resets site_mail and file_temporary_path variables.', 36 | ), 37 | ); 38 | 39 | return $items; 40 | } 41 | 42 | /** 43 | * Executes the build commands. 44 | */ 45 | function _drush_build() { 46 | $commands = array(); 47 | 48 | // Run a registry rebuild at first, then do a full bootstrap. Otherwise, 49 | // this command will fail if the registry has errors. 50 | drush_invoke_process('@self', 'registry-rebuild', array(), array('no-cache-clear' => TRUE)); 51 | drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_FULL); 52 | 53 | $commands[] = array( 54 | 'command' => 'updatedb', 55 | 'options' => array('yes' => TRUE), 56 | ); 57 | $commands[] = array( 58 | 'command' => 'cache-clear', 59 | 'arguments' => array('drush'), 60 | ); 61 | $commands[] = array( 62 | 'command' => 'features-revert-all', 63 | 'options' => array('yes' => TRUE), 64 | ); 65 | $commands[] = array( 66 | 'command' => 'cache-clear', 67 | 'arguments' => array('all'), 68 | ); 69 | $commands[] = array( 70 | 'command' => 'cron', 71 | ); 72 | 73 | // Pass the drushrc file through to drush_invoke_process 74 | $default_options = array(); 75 | if ($config = drush_get_option('config-file')) { 76 | $default_options['config'] = $config; 77 | } 78 | 79 | foreach ($commands as $command) { 80 | $command += array('alias' => '@self', 'arguments' => array(), 'options' => array()); 81 | $command['options'] += $default_options; 82 | 83 | drush_invoke_process($command['alias'], $command['command'], $command['arguments'], $command['options']); 84 | if (drush_get_error() != DRUSH_SUCCESS) { 85 | return drush_set_error('BUILD_FAILED', dt('Build failed on drush @command.', array('@command' => $command['command']))); 86 | } 87 | } 88 | 89 | drush_log(dt('Build completed.'), 'success'); 90 | } 91 | 92 | /** 93 | * Callback for drush devify. 94 | */ 95 | function _drush_devify() { 96 | // Disable modules. 97 | $modules = drush_get_option('disable-modules', array('update')); 98 | if (is_string($modules)) { 99 | $modules = explode(',', $modules); 100 | } 101 | drush_invoke('dis', $modules); 102 | 103 | // Enable modules. 104 | $modules = drush_get_option('enable-modules', array()); 105 | if (is_string($modules)) { 106 | $modules = explode(',', $modules); 107 | } 108 | drush_invoke('en', $modules); 109 | 110 | // Delete variables. 111 | $variables = drush_get_option('delete-variables', array( 112 | 'googleanalytics_account', 113 | )); 114 | if (is_string($variables)) { 115 | $variables = explode(',', $variables); 116 | } 117 | foreach ($variables as $variable) { 118 | variable_del($variable); 119 | } 120 | 121 | // Reset variables. 122 | $variables = drush_get_option('reset-variables', array( 123 | 'preprocess_css' => 0, 124 | 'preprocess_js' => 0, 125 | 'cache' => 0, 126 | 'page_compression' => 0, 127 | )); 128 | if (is_string($variables)) { 129 | // Explode a=b,c=d into an associative array. 130 | $variables_raw = explode(',', $variables); 131 | $variables = array(); 132 | foreach ($variables_raw as $value) { 133 | $variable = explode('=', $value); 134 | if (count($variable) == 2) { 135 | $variables[$variable[0]] = $variable[1]; 136 | } 137 | } 138 | } 139 | foreach ($variables as $name => $value) { 140 | drush_invoke('vset', array($name, $value)); 141 | } 142 | 143 | // Sanitize database. 144 | // @see sql_drush_sql_sync_sanitize() to add your sanitize queries. 145 | drush_invoke('sql-sanitize'); 146 | 147 | drush_log(dt('Devified!'), 'success'); 148 | } 149 | -------------------------------------------------------------------------------- /drush/commands/casperjs/README.md: -------------------------------------------------------------------------------- 1 | # Automated testing 2 | 3 | This directory contains [CasperJS](http://casperjs.org) tests that ensure the 4 | stability of the site. 5 | 6 | ## Installation 7 | 8 | ### Requirements 9 | 10 | * Python 2.6 or greater. 11 | * PhantomJS 1.9.2. 12 | * CasperJS 1.1-beta3. 13 | 14 | ### OSX - Homebrew 15 | Homebrew will install the phantomjs dependency automatically. 16 | 17 | ```bash 18 | brew install casperjs --devel 19 | ``` 20 | 21 | ### Manual installation 22 | 23 | #### Python 24 | 25 | Python is already installed in most platforms. Check the pyhon version with the 26 | following command: 27 | 28 | ```bash 29 | python --version 30 | ``` 31 | 32 | If the above output is less than 2.6, go to https://www.python.org/download, 33 | find the link for your platform at the 2.7 section (even though CasperJS seems 34 | to work on Python 3 we have not tested it yet). 35 | 36 | You can find further installation tips at 37 | http://docs.casperjs.org/en/latest/installation.html#prerequisites 38 | 39 | #### CasperJS 40 | 41 | ```bash 42 | cd /usr/share 43 | sudo git clone git://github.com/n1k0/casperjs.git 44 | cd casperjs 45 | git checkout 1.1-beta3 46 | sudo ln -sf `pwd`/bin/casperjs /usr/local/bin/casperjs 47 | ``` 48 | 49 | #### PhantomJS 50 | 51 | Download phantomjs 1.9.2 http://phantomjs.org/download.html to `/usr/share` 52 | 53 | ```bash 54 | cd /usr/share/phantomjs-1.9.2-linux-x86_64/bin 55 | sudo ln -sf `pwd`/phantomjs /usr/local/bin/phantomjs 56 | ``` 57 | 58 | ### Verify your installation 59 | 60 | When running `casperjs`, the output should be: 61 | 62 | ```bash 63 | casperjs 64 | CasperJS version 1.1.0-beta3 at /usr/share/casperjs, using phantomjs version 1.9.2 65 | ``` 66 | 67 | ## Running tests 68 | Assuming your local environment is set up at http://drupal.local, all tests may 69 | be run with the following command: 70 | 71 | ```bash 72 | cd path-to-drupal-root 73 | drush casperjs --url=http://drupal.local 74 | ``` 75 | 76 | You can also run a specific test by giving it as an argument to the command: 77 | 78 | ```bash 79 | drush casperjs --url=http://drupal.local 80 | ``` 81 | 82 | *NOTE* `drush casperjs` is a wrapper for `casperjs` which sets some useful defaults 83 | when running tests for your Drupal site. Run `drush casperjs -h` for a list of all the 84 | available options and arguments. 85 | 86 | ## Writing tests 87 | 88 | Tests are JavaScript files which are located at the `tests` directory. 89 | They can be organized either by which aspect of the site they test (the homepage, 90 | the contact form, the editorial workflow) or by mapping its name with a module 91 | so it tests the functionality added by that particular module. The choice is 92 | yours to take. 93 | 94 | In order to write a new test, copy any of the existing ones and use it as a 95 | template. Be sure to read through the includes such as `drush/commands/casperjs/includes/common.js` 96 | and drush/commands/casperjs/includes/session.js to find if there are any helper 97 | functions you should be aware of in addition to the ones provided by CasperJS. 98 | 99 | Some useful resources for writing tests are: 100 | * [Navigation steps](http://docs.casperjs.org/en/latest/faq.html#how-does-then-and-the-step-stack-work) 101 | let you wait for certain events such a page getting fully rendered before 102 | running assertions over it. 103 | * The [casper](http://docs.casperjs.org/en/latest/modules/casper.html) object has 104 | commands to interact with the browser such as opening a URL or filling 105 | out a form. 106 | * The [test](http://docs.casperjs.org/en/latest/modules/tester.html) 107 | object contains methods to run assertions over the current context. 108 | * `drush/commands/casperjs/includes/common.js` has a list of useful methods to 109 | navigate through a Drupal project. Rely on these methods as much as possible 110 | in order to simplify your testing code. 111 | * `drush/commands/casperjs/includes/session.js` implements session management so 112 | you can swap from an anonymous user to an authentcated user in just one step. 113 | 114 | ## Cookies 115 | Some tests like will need an authenticated user to work with order to test the 116 | backend. The `drush casperjs` command creates a temporary cookies file at the 117 | temorary directory while running tests to store cookie information and deletes it 118 | the next time tests are run. 119 | 120 | If you need session management in your test call `casper.boilerRun()` to run 121 | your test so that all opened sessions are closed for the next test run. 122 | 123 | ## Tips 124 | ### Taking screenshots 125 | You can take a screenshot and capture markup with `casper.boilerCapture('my-unique-string');`. 126 | This is perfectly fine to commit to your test suite, as this will do nothing 127 | unless you specifically configured your environment to actually save these files. 128 | There are three ways to do this: 129 | 130 | The first is to turn on capturing by exporting 131 | an environment variable: 132 | 133 | ```bash 134 | export BOILER_TEST_CAPTURE=true 135 | ``` 136 | 137 | The second is to run the `drush casperjs` command with debug mode turned on. 138 | See the *Debugging* section for more details on that. 139 | 140 | The third method is to pass `true` as the second argument to `casper.boilerCapture()`. 141 | This will force capturing. Do *not* commit code in this state, as this means 142 | capturing will occur on all environments. 143 | 144 | Once enabled, this command will save a screenshot to `./screenshots/my-unique-string-12345678.jpg` 145 | and the HTML markup to `./pages/my-unique-string-1234578.html`, where `12345678` 146 | is the current timestamp. You may need to create those directories yourself and 147 | give proper write permissions. 148 | 149 | Alternatively, you can use `casper.captureSelector('filename', 'div.some-class');` 150 | to take a screenshot of a given selector. In this case, specify a full filename 151 | to save the capture to, such as `screenshots/my-selector-12345678.jpg`. You can 152 | find more examples about capturing [here](http://docs.casperjs.org/en/latest/modules/casper.html#capture). 153 | 154 | ### Debugging 155 | 156 | If you would like to see a more verbose output of the test suites, you can run 157 | the `drush casperjs` command with the `-d` flag: 158 | 159 | ```bash 160 | drush casperjs -d 161 | ``` 162 | 163 | This will execute CasperJS with `log-level` set to `debug`. In your scripts, you 164 | can log to this debug mode by using `casper.log('my message', 'debug');`. 165 | 166 | In addition, other helpful debugging tools are [`casper.debugPage()`](http://casperjs.readthedocs.org/en/latest/modules/casper.html#debugpage) 167 | and [`casper.debugHTML()`](http://casperjs.readthedocs.org/en/latest/modules/casper.html#debughtml). 168 | 169 | ### Evaluating code 170 | 171 | The [casper.evaluate()](http://docs.casperjs.org/en/latest/modules/casper.html#evaluate) 172 | method (and its alternatives such as `casper.evaluateOrDie()`, `casper.thenEvaluate()` or 173 | `test.assertEvaluate()`) are highly powerful since they will run JavaScript code 174 | on the page just as if you were debugging with the browser's JavaScript console. 175 | -------------------------------------------------------------------------------- /drush/commands/casperjs/casperjs.drush.inc: -------------------------------------------------------------------------------- 1 | 'Wrapper for running CasperJS tests. Accepts extra options for casperjs command.', 15 | 'callback' => 'drush_casperjs', 16 | 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_SITE, 17 | 'arguments' => array( 18 | 'tests' => 'A comma separated list of tests to run. If not provided, all tests at the tests directory will be run.', 19 | ), 20 | 'options' => array( 21 | 'test-root' => 'Overrides the default location of tests.', 22 | 'url' => 'The base URL to use for test requests. Defaults to the URL set by Drush or the current Drush alias.', 23 | 'includes' => 'Comma-separated list of files to include before each test file execution.', 24 | 'cookies-file' => 'Sets the file name to store the persistent cookies. If not provided a random file in the system temporary directory will be used.', 25 | ), 26 | 'examples' => array( 27 | 'drush casperjs --url=http://boiler.local' => 'Runs all tests located at the tests directory against http://boiler.local', 28 | 'drush casperjs --url=http://boiler.local homepage.js' => 'Runs homepage.js test against http://boiler.local.', 29 | 'export BOILER_TEST_CAPTURE=true && drush -v casperjs --url=http://boiler.local --log-level=debug' => 'Runs all tests against http://boiler.local with extra verbose logging and taking screenshots on failed assertions.', 30 | ), 31 | 'allow-additional-options' => TRUE, 32 | ); 33 | 34 | return $items; 35 | } 36 | 37 | /** 38 | * Implements drush_COMMANDFILE(). 39 | */ 40 | function drush_casperjs($tests = NULL) { 41 | 42 | $command = 'casperjs test --verbose'; 43 | 44 | if (!drush_get_option('cookies-file')) { 45 | $cookie_file = drush_tempnam('casper-cookie-'); 46 | $command .= ' --cookies-file=' . drush_escapeshellarg($cookie_file); 47 | } 48 | 49 | if (!drush_get_option('url')) { 50 | $uri = drush_get_context('DRUSH_SELECTED_URI'); 51 | $command .= ' --url=' . drush_escapeshellarg($uri); 52 | } 53 | 54 | // Add include files. 55 | $command .= ' --includes=' . drush_escapeshellarg(dirname(__FILE__) . '/includes/common.js,' . dirname(__FILE__) . '/includes/session.js'); 56 | $command .= ' --pre=' . drush_escapeshellarg(dirname(__FILE__) . '/includes/pre-test.js'); 57 | $command .= ' --post=' . drush_escapeshellarg(dirname(__FILE__) . '/includes/post-test.js'); 58 | if ($includes = drush_get_option('includes')) { 59 | $command .= ',' . $includes; 60 | } 61 | 62 | // Set the root where tests are. Defaults to the tests directory 63 | if (!$root = drush_get_option('test-root')) { 64 | $root = drush_get_context('DRUSH_DRUPAL_ROOT') . '/../tests'; 65 | } 66 | 67 | // If a list of tests to run were passed, append them to the command. 68 | // Otherwise, just set the root where tests are located so CasperJS 69 | // will run all of them. 70 | $tests_to_run = $root; 71 | if ($tests) { 72 | $tests_to_run = ''; 73 | foreach (explode(',', $tests) as $test_file) { 74 | $tests_to_run .= ' ' . drush_escapeshellarg($root . '/' . $test_file); 75 | } 76 | } 77 | $command .= ' ' . $tests_to_run; 78 | 79 | // Append additional CasperJS options to the command. 80 | $args = array(); 81 | foreach (drush_get_original_cli_args_and_options() as $arg) { 82 | // Don't pass some options through. 83 | if (strpos($arg, '--test-root') !== FALSE 84 | || strpos($arg, '--simulate') !== FALSE 85 | || strpos($arg, '--includes') !== FALSE 86 | || strpos($arg, '-') !== 0) { 87 | continue; 88 | } 89 | $args[] = $arg; 90 | } 91 | if (!empty($args)) { 92 | $command .= ' ' . implode(' ', $args); 93 | } 94 | 95 | echo $command . "\n"; 96 | $result = drush_shell_proc_open($command); 97 | if ($result !== 0) { 98 | return drush_set_error('CASPERJS_TEST_FAILED', dt('Tests failed.')); 99 | } 100 | else { 101 | drush_log(dt('Tests succeeded.'), 'success'); 102 | return TRUE; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /drush/commands/casperjs/includes/common.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper methods for navigating through a Drupal site. 3 | * 4 | * This file is included automatically by the casperjs Drush command. 5 | */ 6 | var utils = require('utils'); 7 | var f = utils.format; 8 | 9 | // Set the default timeout to 2 minutes, since the backend experience can be 10 | // quite slow. If you change this value in a test suite, please set it back. 11 | casper.options.waitTimeout = 120000; 12 | 13 | /** 14 | * Run a test suite, ending all sessions when done. 15 | */ 16 | casper.boilerRun = function(time) { 17 | casper.run(function(self) { 18 | casper.boilerEndSession(); 19 | self.test.done(); 20 | }, time); 21 | }; 22 | 23 | /** 24 | * Listen to the open.location event in order to prepend the hostname. 25 | * 26 | * This filter will automatically prepend the full hostname that you are running 27 | * tests against to a given path. For example, if you run 28 | * casper.thenOpen('node/1'), it will convert it to 29 | * http://myhostname/node/1 30 | */ 31 | casper.setFilter('open.location', function(location) { 32 | if (utils.isUndefined(location)) { 33 | location = ""; 34 | } 35 | var cleanPath = location.replace(/^\//, ''); 36 | return casper.cli.get('url') + '/' + cleanPath; 37 | }); 38 | 39 | /** 40 | * Set the viewport to a different breakpoint. 41 | * 42 | * @param string $size 43 | * A breakpoint name. One of mobile, tablet, tablet-landscape or desktop. 44 | */ 45 | casper.thenChangeViewport = function (size) { 46 | this.then(function () { 47 | if (size === 'mobile') { 48 | this.viewport(320, 400); 49 | } else if (size === 'tablet') { 50 | this.viewport(768, 1024); 51 | } else if (size === 'tablet-landscape') { 52 | this.viewport(1020, 1020); 53 | } else if (size === 'desktop') { 54 | this.viewport(1280, 1280); 55 | } else { 56 | test.fail('Responsive Check Not Properly Defined') 57 | } 58 | }); 59 | }; 60 | 61 | /** 62 | * Save page markup to a file. Respect an existing savePageContent function, if 63 | * casper.js core introduces one. 64 | * 65 | * @param String targetFile 66 | * A target filename. 67 | * @return Casper 68 | */ 69 | casper.savePageContent = casper.savePageContent || function(targetFile) { 70 | var fs = require('fs'); 71 | 72 | // Get the absolute path. 73 | targetFile = fs.absolute(targetFile); 74 | // Let other code modify the path. 75 | targetFile = this.filter('page.target_filename', targetFile) || targetFile; 76 | this.log(f("Saving page html to %s", targetFile), "debug"); 77 | // Try saving the file. 78 | try { 79 | fs.write(targetFile, this.getPageContent(), 'w'); 80 | } catch(err) { 81 | this.log(f("Failed to save page html to %s; please check permissions", targetFile), "error"); 82 | this.log(err, "debug"); 83 | return this; 84 | } 85 | 86 | this.log(f("Page html saved to %s", targetFile), "info"); 87 | // Trigger the page.saved event. 88 | this.emit('page.saved', targetFile); 89 | 90 | return this; 91 | }; 92 | 93 | /** 94 | * Capture the markup and screenshot of the page. NOTE: Capturing will only 95 | * occur in one of two ways: either you pass true as the second argument to this 96 | * function (not recommended, except for testing purposes) or if you have set 97 | * the BOILER_TEST_CAPTURE environment variable to true, like so: 98 | * 99 | * $ export BOILER_TEST_CAPTURE=true 100 | * 101 | * @param string filename 102 | * The name of the file to save, without the extension. 103 | * @param boolean force 104 | * Force capturing of screenshots and markup. 105 | */ 106 | casper.boilerCapture = function(filename, force) { 107 | // If we are not capturing, simply return. 108 | if (!this.boilerVariableGet('BOILER_TEST_CAPTURE', false) && !force) { 109 | return; 110 | } 111 | // If we didn't get a filename, use an empty string. 112 | if (utils.isFalsy(filename)) { 113 | filename = ''; 114 | } 115 | // Otherwise, add a dash delimiter to the end. 116 | else { 117 | filename += '-'; 118 | } 119 | // Make the filename unique with a timestamp. 120 | filename += new Date().getTime(); 121 | var screenshot = 'screenshots/' + filename + '.jpg', 122 | markup = 'pages/' + filename + '.html', 123 | prefix = '', 124 | screenshot_url = screenshot, 125 | markup_url = markup; 126 | // If we have a Drupal files directory available, use it. 127 | if (casper.boilerVariableGet('BOILER_FILES_DIRECTORY')) { 128 | prefix = casper.boilerVariableGet('BOILER_FILES_DIRECTORY') + '/testing/'; 129 | screenshot_url = casper.boilerVariableGet('BOILER_FILES_URL') + '/' + screenshot; 130 | markup_url = casper.boilerVariableGet('BOILER_FILES_URL') + '/' + markup; 131 | } 132 | this.capture(prefix + screenshot); 133 | this.test.comment(f('Saved screenshot to %s.', screenshot_url)); 134 | this.savePageContent(prefix + markup); 135 | this.test.comment(f('Saved markup to %s.', markup_url)); 136 | }; 137 | 138 | /** 139 | * Some event listeners to log errors to boilerCapture. 140 | */ 141 | casper.on('error', function() { 142 | casper.boilerCapture('error'); 143 | }); 144 | casper.on('step.error', function() { 145 | casper.boilerCapture('step-error'); 146 | }); 147 | casper.on('step.timeout', function() { 148 | casper.boilerCapture('step-timeout'); 149 | }); 150 | casper.on('waitFor.timeout', function() { 151 | casper.boilerCapture('wait-for-timeout'); 152 | }); 153 | casper.on('started', function() { 154 | // If we have http authentication credentials, use them. 155 | if (casper.boilerVariableGet('BOILER_TEST_HTTP_USERNAME') && casper.boilerVariableGet('BOILER_TEST_HTTP_PASSWORD')) { 156 | this.log("Using HTTP Authentication."); 157 | casper.setHttpAuth(casper.boilerVariableGet('BOILER_TEST_HTTP_USERNAME'), casper.boilerVariableGet('BOILER_TEST_HTTP_PASSWORD')); 158 | } 159 | }); 160 | 161 | /** 162 | * Retrieves an environment variable. 163 | * 164 | * @param String key 165 | * The name of the variable to retrieve. 166 | * @param defaultValue 167 | * The default value to return if no environment variable exists. 168 | * @return 169 | * The value from the environment variable, or the default if none was found, 170 | * or undefined if neither are found. 171 | */ 172 | casper.boilerVariableGet = function(key, defaultValue) { 173 | var variables = require('system').env; 174 | return utils.isUndefined(variables[key]) ? defaultValue : variables[key]; 175 | }; 176 | 177 | // Comment about the status of the BOILER_TEST_CAPTURE variable. 178 | if (casper.boilerVariableGet('BOILER_TEST_CAPTURE')) { 179 | casper.test.comment('Capturing of screenshots and markup is enabled.'); 180 | } 181 | -------------------------------------------------------------------------------- /drush/commands/casperjs/includes/post-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Kills sessions for all users. 3 | */ 4 | casper.test.begin("Logging out sessions for all users.", function suite(test) { 5 | casper.start(); 6 | 7 | casper.then(function() { 8 | casper.each(casper.boilerUsers, function(self, user) { 9 | casper.boilerBeginSession(user); 10 | casper.thenOpen('user/logout', function() { 11 | test.assertHttpStatus(200, user.label + ' has successfully logged out.'); 12 | }); 13 | }); 14 | }); 15 | 16 | casper.run(function() { 17 | test.done(); 18 | }); 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /drush/commands/casperjs/includes/pre-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates sessions for all users. 3 | */ 4 | casper.test.begin("Creating sessions for all users.", function suite(test) { 5 | casper.start(); 6 | 7 | casper.then(function() { 8 | casper.each(casper.boilerUsers, function(self, user) { 9 | casper.boilerCreateSession(user); 10 | }); 11 | }); 12 | 13 | casper.thenOpen('user/logout', function() { 14 | test.assertHttpStatus(403, 'No session is active.'); 15 | }); 16 | 17 | casper.run(function () { 18 | test.done(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /drush/commands/casperjs/includes/session.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Session management tools for CasperJS. 3 | */ 4 | 5 | var utils = require('utils'); 6 | var cookieName; 7 | 8 | /** 9 | * An object of user session cookies, keyed by unique name, ie, editor, writer. 10 | */ 11 | casper.boilerSessions = {}; 12 | 13 | /** 14 | * An array of user objects. 15 | * 16 | * Type here an array of all the sessions you would like 17 | * CasperJS to open when running casper.boilerRun(). 18 | */ 19 | casper.boilerUsers = [ 20 | { 21 | "key": "admin", 22 | "label": "Administrator", 23 | "name" : "admin", 24 | "pass" : "password" 25 | } 26 | ]; 27 | 28 | /** 29 | * Sign in a user using a set of credentials. 30 | * 31 | * @param Object user 32 | * The user object to sign in as. 33 | */ 34 | casper.boilerSignIn = function(user) { 35 | casper.thenOpen('user', function () { 36 | this.fill('form#user-login', { 37 | "name": user.name, 38 | "pass": user.pass 39 | }, true); 40 | }); 41 | 42 | casper.waitForSelector('body.logged-in', function() { 43 | this.log('Logged in as ' + user.label, 'info'); 44 | }, function timeout() { 45 | this.test.fail('Unable to log in as ' + user.label); 46 | }); 47 | }; 48 | 49 | /** 50 | * Creates a session for a user. 51 | * 52 | * @param Object user 53 | * The user object, with credentials. 54 | */ 55 | casper.boilerCreateSession = function(user) { 56 | casper.boilerSignIn(user); 57 | 58 | // Store the cookie under a separate name, so we can do the rest of the 59 | // tests as an anonymous user. 60 | casper.then(function () { 61 | casper.each(casper.page.cookies, function (self, cookie) { 62 | if (cookie.name.match(/^SESS/)) { 63 | // Store the cookie name so we can use it later. 64 | cookieName = cookie.name; 65 | // Store the cookie. 66 | casper.boilerSessions[user.key] = cookie; 67 | // Delete the cookie. 68 | casper.boilerEndSession(); 69 | } 70 | }); 71 | }); 72 | 73 | casper.thenOpen('user', function () { 74 | var success = !this.exists('body.logged-in') && utils.isObject(casper.boilerSessions[user.key]); 75 | this.test.assert(success, user.label + ' session cookie has been stored.'); 76 | }); 77 | }; 78 | 79 | /** 80 | * Begin a session as a user specified by key. 81 | * 82 | * @param String key 83 | * The key of the user, such as editor, writer, etc. 84 | */ 85 | casper.boilerBeginSession = function(key) { 86 | casper.then(function() { 87 | var label = key; 88 | // If a full user object was passed, parse it for just the key. 89 | if (!utils.isUndefined(key.key)) { 90 | label = key.label; 91 | key = key.key; 92 | } 93 | if (utils.isUndefined(casper.boilerSessions[key])) { 94 | this.test.fail("Unable to find session for user " + key); 95 | } 96 | casper.page.addCookie(casper.boilerSessions[key]); 97 | this.log('Began session as ' + label, 'info'); 98 | }); 99 | }; 100 | 101 | /** 102 | * End a session, switching back to an anonymous user. 103 | */ 104 | casper.boilerEndSession = function() { 105 | casper.then(function() { 106 | casper.page.deleteCookie(cookieName); 107 | this.log('Ended authenticated session.', 'info'); 108 | }); 109 | }; 110 | 111 | /** 112 | * Start a test suite, signed in as a certain user. 113 | * 114 | * @param String key 115 | * The key of the user, such as editor, writer, etc. 116 | */ 117 | casper.boilerStartAs = function(key) { 118 | casper.start(); 119 | casper.boilerBeginSession(key); 120 | }; 121 | -------------------------------------------------------------------------------- /drush/commands/downsync.drush.inc: -------------------------------------------------------------------------------- 1 | "Sync one environment's db and files to another.", 15 | 'arguments' => array( 16 | 'source-alias' => 'Alias of the source site to copy from.', 17 | 'destination-alias' => 'Alias of the destination site to copy to.', 18 | ), 19 | 'examples' => array( 20 | 'drush downsync @prod @local' => 'sql-sync the database and rsync the files from @prod to @local', 21 | ), 22 | 'aliases' => array('dsync'), 23 | 'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, 24 | 'drush dependencies' => array('sql', 'core'), 25 | ); 26 | return $items; 27 | } 28 | 29 | /** 30 | * Actual function run by the downsync command. 31 | */ 32 | function drush_downsync($source = NULL, $destination = NULL) { 33 | // Make sure we have the source-dump and target-dump options. 34 | $source_dump = drush_get_option('source-dump'); 35 | if (!isset($source_dump)) { 36 | drush_set_option('source-dump', '/tmp/source-dump.sql'); 37 | } 38 | 39 | $target_dump = drush_get_option('target-dump'); 40 | if (!isset($target_dump)) { 41 | drush_set_option('target-dump', '/tmp/target-dump.sql'); 42 | } 43 | 44 | // Execute a drush sql-sync 45 | print dt('SQL Sync running... NOTE: if you do not have ssh passwordless logins setup, you may be asked for your password multiple times.'); 46 | 47 | drush_invoke('sql-sync', array($source, $destination)); 48 | 49 | // Rsync the files. 50 | print dt('Rsync-ing files...'); 51 | drush_invoke('rsync', array($source . ':%files', $destination . ':%files')); 52 | } 53 | -------------------------------------------------------------------------------- /drush/commands/policy.drush.inc: -------------------------------------------------------------------------------- 1 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /drush/commands/registry_rebuild/README.txt: -------------------------------------------------------------------------------- 1 | Registry Rebuild 2 | ---------------- 3 | 4 | THIS IS NOT A MODULE. PLEASE READ BELOW. 5 | 6 | There are times in Drupal 7+ when the registry gets hopelessly hosed and you 7 | need to rebuild the registry (a list of PHP classes and the files they go with). 8 | Sometimes, though, you can't do this regular cache-clear activity because some 9 | class is required when the system is trying to bootstrap. 10 | 11 | When would you need Registry Rebuild? 12 | ------------------------------------- 13 | 14 | You might get something like: 15 | 16 | PHP Fatal error: Class 'EntityAPIControllerExportable' not found in 17 | ...sites/all/modules/rules/includes/rules.core.inc on line 11 18 | 19 | If this happens when you're trying to run update.php, and happens when you're 20 | trying to clear your cache, well, you have some trouble. That's what Registry 21 | Rebuild is for. 22 | 23 | When would you *not* need Registry Rebuild? 24 | ------------------------------------------- 25 | If you can access any page, or install a module, or run update.php, you almost 26 | certainly don't need Registry Rebuild. 27 | 28 | You can run registry_rebuild with or without drush. See below. 29 | 30 | How To Use It (with drush) 31 | -------------------------- 32 | 1. Make a backup of your database. 33 | 2. drush dl registry_rebuild will download the current recommended version and 34 | place it in your .drush folder. Or you can copy the directory 35 | registry_rebuild from this package into your 36 | ~/.drush folder (or other appropriate folder) 37 | 3. Run "drush rr" 38 | 39 | How To Use It (without drush) 40 | ----------------------------- 41 | This isn't really a module, but it's just packaged as a module to make it so 42 | it's easy to find and people can download it as a package. 43 | 44 | 1. Make a backup of your database. 45 | 2. Download and install as usual where you put modules (sites/all/modules is 46 | most common) 47 | 3. You don't need to enable it. If you were able to enable it you wouldn't 48 | need it. See above. 49 | 4. Either run it from the command line: 50 | cd sites/all/modules/registry_rebuild 51 | php registry_rebuild.php 52 | OR 53 | point your web browser to 54 | http://example.com/sites/all/modules/registry_rebuild/registry_rebuild.php 55 | Changing "example.com" to your own site's base URL of course. 56 | 4. You should see something like this: 57 | 58 | DRUPAL_ROOT is /home/rfay/workspace/commerce. 59 | There were 631 files in the registry before and 508 files now. 60 | If you don't see any crazy fatal errors, your registry has been rebuilt. You will probably want to flush your caches now. 61 | 62 | 5. Hopefully you'll now be able to go about your affairs in peace, updating, 63 | clearing cache, etc. 64 | 65 | This package comes with no guarantee explicit or implicit. 66 | 67 | There's no reason it should do any harm to your install. But there can be lots 68 | of things wrong with a system, and the registry problem is not the fix for 69 | everything. 70 | 71 | -------------------------------------------------------------------------------- /drush/commands/registry_rebuild/registry_rebuild.drush.inc: -------------------------------------------------------------------------------- 1 | 'Rebuild the registry table (for classes) and the system table (for module locations) in a Drupal install.', 31 | 'callback' => 'drush_registry_rebuild', 32 | 'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap. 33 | 'options' => array( 34 | 'no-cache-clear' => 'Rebuild the registry only, do not clear caches, unless --fire-bazooka is also used.', 35 | 'fire-bazooka' => 'Truncate registry and registry_file tables and build them from scratch. Forces all caches clear.', 36 | ), 37 | 'examples' => array( 38 | 'drush rr --no-cache-clear' => 'Rebuild the registry only, do not clear caches, unless --fire-bazooka is also used.', 39 | 'drush rr --fire-bazooka' => 'Truncate registry and registry_file tables and build them from scratch. Forces all caches clear.', 40 | ), 41 | 'aliases' => array('rr'), 42 | ); 43 | 44 | return $items; 45 | } 46 | 47 | /** 48 | * Rebuild the registry. 49 | * 50 | * Before calling this we need to be bootstrapped to DRUPAL_BOOTSTRAP_DATABASE. 51 | */ 52 | function drush_registry_rebuild() { 53 | define('MAINTENANCE_MODE', 'update'); 54 | ini_set('memory_limit', -1); 55 | if (!drush_bootstrap_to_phase(DRUSH_BOOTSTRAP_DRUPAL_DATABASE)) { 56 | return drush_set_error('DRUPAL_SITE_NOT_FOUND', dt('You need to specify an alias or run this command within a drupal site.')); 57 | } 58 | $include_dir = DRUPAL_ROOT . '/includes'; 59 | $module_dir = DRUPAL_ROOT . '/modules'; 60 | // Use core directory if it exists. 61 | if (file_exists(DRUPAL_ROOT . '/core/includes/bootstrap.inc')) { 62 | $include_dir = DRUPAL_ROOT . '/core/includes'; 63 | $module_dir = DRUPAL_ROOT . '/core/modules'; 64 | } 65 | 66 | $includes = array( 67 | $include_dir . '/bootstrap.inc', 68 | $include_dir . '/common.inc', 69 | $include_dir . '/database.inc', 70 | $include_dir . '/schema.inc', 71 | $include_dir . '/actions.inc', 72 | $include_dir . '/entity.inc', 73 | $module_dir . '/system/system.module', 74 | $include_dir . '/database/query.inc', 75 | $include_dir . '/database/select.inc', 76 | $include_dir . '/registry.inc', 77 | $include_dir . '/module.inc', 78 | $include_dir . '/menu.inc', 79 | $include_dir . '/file.inc', 80 | $include_dir . '/theme.inc', 81 | ); 82 | 83 | if (drush_drupal_major_version() == 7) { 84 | $cache_lock_path_absolute = variable_get('lock_inc'); 85 | if (!empty($cache_lock_path_absolute)) { 86 | $cache_lock_path_relative = DRUPAL_ROOT . '/'. variable_get('lock_inc'); 87 | // Ensure that the configured lock.inc really exists at that location and 88 | // is accessible. Otherwise we use the core lock.inc as fallback. 89 | if (is_readable($cache_lock_path_relative) && is_file($cache_lock_path_relative)) { 90 | $includes[] = $cache_lock_path_relative; 91 | drush_log(dt("We will use relative variant of lock.inc: @lock", array('@lock' => $cache_lock_path_relative))); 92 | } 93 | elseif (is_readable($cache_lock_path_absolute) && is_file($cache_lock_path_absolute)) { 94 | $includes[] = $cache_lock_path_absolute; 95 | drush_log(dt("We will use absolute variant of lock.inc: @lock", array('@lock' => $cache_lock_path_absolute))); 96 | } 97 | else { 98 | drush_log(dt('We will use core implementation of lock.inc as fallback.')); 99 | $includes[] = DRUPAL_ROOT . '/includes/lock.inc'; 100 | } 101 | } 102 | else { 103 | $includes[] = DRUPAL_ROOT . '/includes/lock.inc'; 104 | } 105 | } 106 | elseif (drush_drupal_major_version() > 7) { 107 | // TODO 108 | // http://api.drupal.org/api/drupal/namespace/Drupal!Core!Lock/8 109 | $includes[] = $module_dir . '/entity/entity.module'; 110 | $includes[] = $module_dir . '/entity/entity.controller.inc'; 111 | } 112 | // In Drupal 6 the configured lock.inc is already loaded during 113 | // DRUSH_BOOTSTRAP_DRUPAL_DATABASE 114 | 115 | foreach ($includes as $include) { 116 | if (file_exists($include)) { 117 | require_once($include); 118 | } 119 | } 120 | 121 | // We may need to clear also Drush 5+ internal cache first. 122 | drush_log(dt("This DRUSH_MAJOR_VERSION is: @ver", array('@ver' => DRUSH_MAJOR_VERSION))); 123 | if (DRUSH_MAJOR_VERSION > 4) { 124 | drush_cache_clear_drush(); 125 | drush_log(dt('Internal Drush cache cleared with drush_cache_clear_drush (1).')); 126 | } 127 | 128 | // This section is not functionally important. It's just using the 129 | // registry_get_parsed_files() so that it can report the change. Drupal 7 only. 130 | if (drush_drupal_major_version() == 7) { 131 | $connection_info = Database::getConnectionInfo(); 132 | $driver = $connection_info['default']['driver']; 133 | require_once $include_dir . '/database/' . $driver . '/query.inc'; 134 | $parsed_before = registry_get_parsed_files(); 135 | } 136 | 137 | // Separate bootstrap cache exists only in Drupal 7 or newer. 138 | // They are cleared later again via drupal_flush_all_caches(). 139 | if (drush_drupal_major_version() == 7) { 140 | cache_clear_all('lookup_cache', 'cache_bootstrap'); 141 | cache_clear_all('variables', 'cache_bootstrap'); 142 | cache_clear_all('module_implements', 'cache_bootstrap'); 143 | drush_log(dt('Bootstrap caches have been cleared in DRUSH_BOOTSTRAP_DRUPAL_DATABASE.')); 144 | } 145 | elseif (drush_drupal_major_version() >= 8) { 146 | cache('bootstrap')->deleteAll(); 147 | drush_log(dt('Bootstrap caches have been cleared in DRUSH_BOOTSTRAP_DRUPAL_DATABASE.')); 148 | } 149 | 150 | // We later run system_rebuild_module_data() and registry_update() on Drupal 7 via 151 | // D7-only registry_rebuild() wrapper, which is run inside drupal_flush_all_caches(). 152 | // It is an equivalent of module_rebuild_cache() in D5-D6 and is normally run via 153 | // our universal wrapper registry_rebuild_cc_all() -- see further below. 154 | // However, we are still on the DRUPAL_BOOTSTRAP_SESSION level here, 155 | // and we want to make the initial rebuild as atomic as possible, so we can't 156 | // run everything from registry_rebuild_cc_all() yet, so we run an absolute 157 | // minimum we can at this stage, core specific. 158 | drush_log(dt('We are on the DRUSH_BOOTSTRAP_DRUPAL_DATABASE level still.')); 159 | if (drush_drupal_major_version() == 7) { 160 | registry_rebuild(); // D7 only 161 | drush_log(dt('The registry has been rebuilt via registry_rebuild (A).'), 'success'); 162 | } 163 | elseif (drush_drupal_major_version() > 7) { 164 | system_rebuild_module_data(); // D8+ 165 | drush_log(dt('The registry has been rebuilt via system_rebuild_module_data (A).'), 'success'); 166 | } 167 | else { // D5-D6 168 | module_list(TRUE, FALSE); 169 | module_rebuild_cache(); 170 | drush_log(dt('The registry has been rebuilt via module_rebuild_cache (A).'), 'success'); 171 | } 172 | 173 | // We may need to clear also Drush 5+ internal cache at this point again. 174 | if (DRUSH_MAJOR_VERSION > 4) { 175 | drush_cache_clear_drush(); 176 | drush_log(dt('Internal Drush cache cleared with drush_cache_clear_drush (2).')); 177 | } 178 | 179 | drush_log(dt('Bootstrapping to DRUPAL_BOOTSTRAP_FULL.')); 180 | drush_bootstrap_to_phase(DRUSH_BOOTSTRAP_DRUPAL_FULL); 181 | // We can run our wrapper now, since we are in a full bootstrap already. 182 | // Note that the wrapper normally honors the --no-cache-clear option if used. 183 | drush_registry_rebuild_cc_all(); 184 | drush_log(dt('The registry has been rebuilt via drush_registry_rebuild_cc_all (B).'), 'success'); 185 | 186 | if (drush_get_option('fire-bazooka') && drush_drupal_major_version() == 7) { 187 | $force_all_cache_clear = TRUE; 188 | if (drush_get_option('no-cache-clear')) { 189 | // Force all caches clear before rebuilding tables from scratch, 190 | // but only if --no-cache-clear is used, since otherwise 191 | // it already has been done above. 192 | drush_registry_rebuild_cc_all(); 193 | drush_log(dt('Forced pre-fire-bazooka extra all caches clear.')); 194 | } 195 | db_truncate('registry')->execute(); 196 | db_truncate('registry_file')->execute(); 197 | drush_log(dt('The registry_file and registry tables truncated with --fire-bazooka.')); 198 | // We have to force API-based rebuild integrated with cache clears 199 | // directly after truncating registry tables. 200 | drush_registry_rebuild_cc_all(); 201 | drush_log(dt('The registry has been rebuilt via drush_registry_rebuild_cc_all (C).'), 'success'); 202 | } 203 | 204 | // Extra cleanup available for D7 only. 205 | if (drush_drupal_major_version() == 7) { 206 | $parsed_after = registry_get_parsed_files(); 207 | // Remove files which don't exist anymore. 208 | $filenames = array(); 209 | foreach ($parsed_after as $filename => $file) { 210 | if (!file_exists($filename)) { 211 | $filenames[] = $filename; 212 | } 213 | } 214 | if (!empty($filenames)) { 215 | db_delete('registry_file') 216 | ->condition('filename', $filenames) 217 | ->execute(); 218 | db_delete('registry') 219 | ->condition('filename', $filenames) 220 | ->execute(); 221 | $dt_args = array( 222 | '@files' => implode(', ', $filenames), 223 | ); 224 | $singular = 'Manually deleted 1 stale file from the registry.'; 225 | $plural = 'Manually deleted @count stale files from the registry.'; 226 | drush_log(format_plural(count($filenames), $singular, $plural), 'success'); 227 | $singular = "A file has been declared in a module's .info, but could not be found. This is probably indicative of a bug. The missing file is @files."; 228 | $plural = "@count files were declared in a module's .info, but could not be found. This is probably indicative of a bug. The missing files are @files."; 229 | drush_log(format_plural(count($filenames), $singular, $plural, $dt_args), 'warning'); 230 | } 231 | $parsed_after = registry_get_parsed_files(); 232 | $message = 'There were @parsed_before files in the registry before and @parsed_after files now.'; 233 | $dt_args = array( 234 | '@parsed_before' => count($parsed_before), 235 | '@parsed_after' => count($parsed_after), 236 | ); 237 | drush_log(dt($message, $dt_args)); 238 | drush_registry_rebuild_cc_all(); 239 | } 240 | 241 | // Everything done. 242 | drush_log(dt('All registry rebuilds have been completed.'), 'success'); 243 | } 244 | 245 | /** 246 | * Registry Rebuild needs to aggressively clear all caches, 247 | * not just some bins (at least to attempt it) also *before* 248 | * attempting to rebuild registry, or it may not be able 249 | * to fix the problem at all, if it relies on some cached 250 | * and no longer valid data/paths etc. This problem has been 251 | * confirmed and reproduced many times with option --fire-bazooka 252 | * which is available only in the Drush variant, but it confirms 253 | * the importance of starting with real, raw and not cached 254 | * in any way site state. While the --no-cache-clear option 255 | * still disables this procedure, --fire-bazooka takes precedence 256 | * and forces all caches clear action. All caches are cleared 257 | * by default in the PHP script variant. 258 | */ 259 | function drush_registry_rebuild_cc_all() { 260 | if (!drush_get_option('no-cache-clear') || $force_all_cache_clear) { 261 | if (function_exists('cache_clear_all') || drush_drupal_major_version() < 8) { 262 | cache_clear_all('*', 'cache', TRUE); 263 | cache_clear_all('*', 'cache_form', TRUE); 264 | } 265 | else { 266 | cache('cache')->deleteAll(); 267 | cache('cache_form')->deleteAll(); 268 | } 269 | 270 | if (function_exists('module_rebuild_cache') || (drush_drupal_major_version() >= 5 && drush_drupal_major_version() < 7)) { // D5-D6 271 | module_list(TRUE, FALSE); 272 | module_rebuild_cache(); 273 | } 274 | 275 | if (function_exists('drupal_flush_all_caches') || drush_drupal_major_version() >= 6) { // D6+ 276 | drupal_flush_all_caches(); 277 | } 278 | else { // D5 279 | cache_clear_all(); 280 | system_theme_data(); 281 | node_types_rebuild(); 282 | menu_rebuild(); 283 | } 284 | drush_log(dt('All caches have been cleared with drush_registry_rebuild_cc_all.'), 'success'); 285 | } 286 | else { 287 | if (drush_drupal_major_version() == 7) { 288 | registry_rebuild(); // D7 only 289 | drush_log(dt('The registry has been rebuilt via registry_rebuild (no-cache-clear).'), 'success'); 290 | } 291 | elseif (drush_drupal_major_version() > 7) { 292 | system_rebuild_module_data(); // D8+ 293 | drush_log(dt('The registry has been rebuilt via system_rebuild_module_data (no-cache-clear).'), 'success'); 294 | } 295 | else { // D5-D6 296 | module_list(TRUE, FALSE); 297 | module_rebuild_cache(); 298 | drush_log(dt('The registry has been rebuilt via module_rebuild_cache (no-cache-clear).'), 'success'); 299 | } 300 | drush_log(dt('The Drupal caches have NOT been cleared after all registry rebuilds.'), 'warning'); 301 | drush_log(dt('It is highly recommended you clear the Drupal caches as soon as possible.'), 'warning'); 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /drush/commands/registry_rebuild/registry_rebuild.php: -------------------------------------------------------------------------------- 1 | \n"; 13 | define('MAINTENANCE_MODE', 'update'); 14 | 15 | global $_SERVER; 16 | $_SERVER['REMOTE_ADDR'] = 'nothing'; 17 | 18 | global $include_dir; 19 | $include_dir = DRUPAL_ROOT . '/includes'; 20 | $module_dir = DRUPAL_ROOT . '/modules'; 21 | // Use core directory if it exists. 22 | if (file_exists(DRUPAL_ROOT . '/core/includes/bootstrap.inc')) { 23 | $include_dir = DRUPAL_ROOT . '/core/includes'; 24 | $module_dir = DRUPAL_ROOT . '/core/modules'; 25 | } 26 | 27 | $includes = array( 28 | $include_dir . '/bootstrap.inc', 29 | $include_dir . '/common.inc', 30 | $include_dir . '/database.inc', 31 | $include_dir . '/schema.inc', 32 | $include_dir . '/actions.inc', 33 | $include_dir . '/entity.inc', 34 | $module_dir . '/system/system.module', 35 | $include_dir . '/database/query.inc', 36 | $include_dir . '/database/select.inc', 37 | $include_dir . '/registry.inc', 38 | $include_dir . '/module.inc', 39 | $include_dir . '/menu.inc', 40 | $include_dir . '/file.inc', 41 | $include_dir . '/theme.inc', 42 | ); 43 | 44 | if (function_exists('registry_rebuild')) { // == D7 45 | $cache_lock_path_absolute = variable_get('lock_inc'); 46 | if (!empty($cache_lock_path_absolute)) { 47 | $cache_lock_path_relative = DRUPAL_ROOT . '/'. variable_get('lock_inc'); 48 | // Ensure that the configured lock.inc really exists at that location and 49 | // is accessible. Otherwise we use the core lock.inc as fallback. 50 | if (is_readable($cache_lock_path_relative) && is_file($cache_lock_path_relative)) { 51 | $includes[] = $cache_lock_path_relative; 52 | print "We will use relative variant of lock.inc.
\n"; 53 | } 54 | elseif (is_readable($cache_lock_path_absolute) && is_file($cache_lock_path_absolute)) { 55 | $includes[] = $cache_lock_path_absolute; 56 | print "We will use absolute variant of lock.inc.
\n"; 57 | } 58 | else { 59 | print "We will use core implementation of lock.inc as fallback.
\n"; 60 | $includes[] = DRUPAL_ROOT . '/includes/lock.inc'; 61 | } 62 | } 63 | else { 64 | $includes[] = DRUPAL_ROOT . '/includes/lock.inc'; 65 | } 66 | } 67 | elseif (!function_exists('cache_clear_all')) { // D8+ 68 | // TODO 69 | // http://api.drupal.org/api/drupal/namespace/Drupal!Core!Lock/8 70 | $includes[] = $module_dir . '/entity/entity.module'; 71 | $includes[] = $module_dir . '/entity/entity.controller.inc'; 72 | } 73 | // In Drupal 6 the configured lock.inc is already loaded during 74 | // DRUSH_BOOTSTRAP_DRUPAL_DATABASE 75 | 76 | foreach ($includes as $include) { 77 | if (file_exists($include)) { 78 | require_once($include); 79 | } 80 | } 81 | 82 | print "Bootstrapping to DRUPAL_BOOTSTRAP_SESSION
\n"; 83 | drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION); 84 | 85 | registry_rebuild_rebuild(); 86 | 87 | /** 88 | * Find the drupal root directory by looking in parent directories. 89 | * If unable to discover it, fail and exit. 90 | */ 91 | function define_drupal_root() { 92 | // This is the smallest number of directories to go up: from /sites/all/modules/registry_rebuild. 93 | $parent_count = 4; 94 | // 8 seems reasonably far to go looking up. 95 | while ($parent_count < 8) { 96 | $dir = realpath(getcwd() . str_repeat('/..', $parent_count)); 97 | if (file_exists($dir . '/index.php')) { 98 | return $dir; 99 | } 100 | $parent_count++; 101 | } 102 | print "Failure: Unable to discover DRUPAL_ROOT. You may want to explicitly define it near the top of registry_rebuild.php"; 103 | exit(1); 104 | } 105 | 106 | /** 107 | * Before calling this we need to be bootstrapped to DRUPAL_BOOTSTRAP_SESSION. 108 | */ 109 | function registry_rebuild_rebuild() { 110 | // This section is not functionally important. It's just using the 111 | // registry_get_parsed_files() so that it can report the change. Drupal 7 only. 112 | if (function_exists('registry_rebuild')) { 113 | $connection_info = Database::getConnectionInfo(); 114 | $driver = $connection_info['default']['driver']; 115 | global $include_dir; 116 | require_once $include_dir . '/database/' . $driver . '/query.inc'; 117 | $parsed_before = registry_get_parsed_files(); 118 | } 119 | 120 | // Separate bootstrap cache exists only in Drupal 7 or newer. 121 | // They are cleared later again via drupal_flush_all_caches(). 122 | if (function_exists('registry_rebuild')) { // D7 123 | cache_clear_all('lookup_cache', 'cache_bootstrap'); 124 | cache_clear_all('variables', 'cache_bootstrap'); 125 | cache_clear_all('module_implements', 'cache_bootstrap'); 126 | print "Bootstrap caches have been cleared in DRUPAL_BOOTSTRAP_SESSION
\n"; 127 | } 128 | elseif (!function_exists('cache_clear_all')) { // D8+ 129 | cache('bootstrap')->deleteAll(); 130 | print "Bootstrap caches have been cleared in DRUPAL_BOOTSTRAP_SESSION
\n"; 131 | } 132 | 133 | // We later run system_rebuild_module_data() and registry_update() on Drupal 7 via 134 | // D7-only registry_rebuild() wrapper, which is run inside drupal_flush_all_caches(). 135 | // It is an equivalent of module_rebuild_cache() in D5-D6 and is normally run via 136 | // our universal wrapper registry_rebuild_cc_all() -- see further below. 137 | // However, we are still on the DRUPAL_BOOTSTRAP_SESSION level here, 138 | // and we want to make the initial rebuild as atomic as possible, so we can't 139 | // run everything from registry_rebuild_cc_all() yet, so we run an absolute 140 | // minimum we can at this stage, core specific. 141 | if (function_exists('registry_rebuild')) { // D7 only 142 | print "Doing registry_rebuild() in DRUPAL_BOOTSTRAP_SESSION
\n"; 143 | registry_rebuild(); 144 | } 145 | elseif (!function_exists('registry_rebuild') && function_exists('system_rebuild_module_data')) { // D8+ 146 | print "Doing system_rebuild_module_data() in DRUPAL_BOOTSTRAP_SESSION
\n"; 147 | system_rebuild_module_data(); 148 | } 149 | else { // D5-D6 150 | print "Doing module_rebuild_cache() in DRUPAL_BOOTSTRAP_SESSION
\n"; 151 | module_list(TRUE, FALSE); 152 | module_rebuild_cache(); 153 | } 154 | 155 | print "Bootstrapping to DRUPAL_BOOTSTRAP_FULL
\n"; 156 | drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); 157 | // We can run our wrapper now, since we are in a full bootstrap already. 158 | print "Rebuilding registry via registry_rebuild_cc_all in DRUPAL_BOOTSTRAP_FULL
\n"; 159 | registry_rebuild_cc_all(); 160 | 161 | // Extra cleanup available for D7 only. 162 | if (function_exists('registry_rebuild')) { 163 | $parsed_after = registry_get_parsed_files(); 164 | // Remove files which don't exist anymore. 165 | $filenames = array(); 166 | foreach ($parsed_after as $filename => $file) { 167 | if (!file_exists($filename)) { 168 | $filenames[] = $filename; 169 | } 170 | } 171 | if (!empty($filenames)) { 172 | db_delete('registry_file') 173 | ->condition('filename', $filenames) 174 | ->execute(); 175 | db_delete('registry') 176 | ->condition('filename', $filenames) 177 | ->execute(); 178 | print("Deleted " . count($filenames) . ' stale files from registry manually.'); 179 | } 180 | $parsed_after = registry_get_parsed_files(); 181 | print "There were " . count($parsed_before) . " files in the registry before and " . count($parsed_after) . " files now.
\n"; 182 | registry_rebuild_cc_all(); 183 | } 184 | print "If you don't see any crazy fatal errors, your registry has been rebuilt.
\n"; 185 | } 186 | 187 | /** 188 | * Registry Rebuild needs to aggressively clear all caches, 189 | * not just some bins (at least to attempt it) also *before* 190 | * attempting to rebuild registry, or it may not be able 191 | * to fix the problem at all, if it relies on some cached 192 | * and no longer valid data/paths etc. This problem has been 193 | * confirmed and reproduced many times with option --fire-bazooka 194 | * which is available only in the Drush variant, but it confirms 195 | * the importance of starting with real, raw and not cached 196 | * in any way site state. While the --no-cache-clear option 197 | * still disables this procedure, --fire-bazooka takes precedence 198 | * and forces all caches clear action. All caches are cleared 199 | * by default in the PHP script variant. 200 | */ 201 | function registry_rebuild_cc_all() { 202 | if (function_exists('cache_clear_all')) { 203 | cache_clear_all('*', 'cache', TRUE); 204 | cache_clear_all('*', 'cache_form', TRUE); 205 | } 206 | else { 207 | cache('cache')->deleteAll(); 208 | cache('cache_form')->deleteAll(); 209 | } 210 | 211 | if (function_exists('module_rebuild_cache')) { // D5-D6 212 | module_list(TRUE, FALSE); 213 | module_rebuild_cache(); 214 | } 215 | 216 | if (function_exists('drupal_flush_all_caches')) { // D6+ 217 | drupal_flush_all_caches(); 218 | } 219 | else { // D5 220 | cache_clear_all(); 221 | system_theme_data(); 222 | node_types_rebuild(); 223 | menu_rebuild(); 224 | } 225 | print "All caches have been cleared with registry_rebuild_cc_all.
\n"; 226 | } 227 | -------------------------------------------------------------------------------- /drush/drushrc.php: -------------------------------------------------------------------------------- 1 | TRUE); 211 | # $command_specific['dl'] = array('cvscredentials' => 'user:pass'); 212 | 213 | // Specify additional directories to search for scripts 214 | // Separate by : (Unix-based systems) or ; (Windows). 215 | # $command_specific['script']['script-path'] = 'sites/all/scripts:profiles/myprofile/scripts'; 216 | 217 | // Always show release notes when running pm-update or pm-updatecode 218 | # $command_specific['pm-update'] = array('notes' => TRUE); 219 | # $command_specific['pm-updatecode'] = array('notes' => TRUE); 220 | 221 | // Set a predetermined username and password when using site-install. 222 | # $command_specific['site-install'] = array('account-name' => 'alice', 'account-pass' => 'secret'); 223 | 224 | // List of drush commands or aliases that should override built-in 225 | // shell functions and commands; otherwise, built-ins override drush 226 | // commands. Default is help,dd,sa. 227 | // Warning: bad things can happen if you put the wrong thing here 228 | // (e.g. eval, grep), so be cautious. 229 | // If a drush command overrides a built-in command (e.g. bash help), 230 | // then you can use the `builtin` operator to run the built-in version 231 | // (e.g. `builtin help` to show bash help instead of drush help.) 232 | // If a drush command overrides a shell command (e.g. grep), then 233 | // you can use the regular shell command by typing in the full path 234 | // to the command (e.g. /bin/grep). 235 | # $command_specific['core-cli'] = array('override' => 'help,dd,sa'); 236 | 237 | // Provide a default directory to run on drush casperjs. 238 | # $command_specific['casperjs']['test-root'] = str_replace('drush', 'tests/casperjs', dirname(__FILE__)); 239 | 240 | /** 241 | * Load local development override configuration, if available. 242 | * 243 | * Use drushrc.local.php to override Drush configuration on secondary (staging, 244 | * development, etc) installations of this site. 245 | * 246 | * Keep this code block at the end of this file to take full effect. 247 | */ 248 | if (file_exists(dirname(__FILE__) . '/drushrc.local.php')) { 249 | include_once dirname(__FILE__) . '/drushrc.local.php'; 250 | } 251 | -------------------------------------------------------------------------------- /drush/readme.md: -------------------------------------------------------------------------------- 1 | #Drush configurations 2 | 3 | ##How to use this directory 4 | 5 | Drush doesn't by default know to search this directory. To work around that we need 6 | to add this awesome snippet to our local drushrc.php file. 7 | 8 | ```php 9 | // Load a drushrc.php file from the 'drush' folder at the root of the current 10 | // git repository. Customize as desired. 11 | // (Script by grayside; @see: http://grayside.org/node/93) 12 | $repo_dir = drush_get_option('root') ? drush_get_option('root') : getcwd(); 13 | $success = drush_shell_exec('cd %s && git rev-parse --show-toplevel 2> ' . drush_bit_bucket(), $repo_dir); 14 | if ($success) { 15 | $output = drush_shell_exec_output(); 16 | $repo = $output[0]; 17 | $options['config'] = $repo . '/drush/drushrc.php'; 18 | $options['include'] = $repo . '/drush/commands'; 19 | $options['alias-path'] = $repo . '/drush/aliases'; 20 | } 21 | ``` 22 | 23 | Once the above snippet is in our drushrc.php file then drush will know to read our 24 | custom drushrc.php and to search our commands and aliases directory for commands 25 | and aliases. 26 | 27 | ###Aliases 28 | The aliases directory is used to store aliases specific to your project. This is a great 29 | place to share aliases such as _@example.staging_, _@example.live_, _@example.rc_ etc.. 30 | 31 | Be cautious about not storing local specific alias because they probably wont work in 32 | every environment. 33 | 34 | ###Commands 35 | The commands directory is used to store drush commands you would like to share 36 | with your entire team. This is a great place for your custom drush xyz command. 37 | 38 | By default we include the __Registry Rebuild__, __Build__ and __Devify commands. 39 | 40 | ####Registry Rebuild 41 | Instead of trying to explain what it does. Here's a snippet from its [project 42 | page](http://drupal.org/project/registry_rebuild). 43 | 44 | >>There are times in Drupal 7 when the registry gets hopelessly hosed and you need to rebuild the registry 45 | (a list of PHP classes and the files they go with). Sometimes, though, you can't do this regular 46 | cache-clear activity because some class is required when the system is trying to bootstrap. 47 | 48 | ####Build 49 | The build command is nothing but a simple drush commands that calls other drush commands 50 | such as updatedb, features-revert-all, and cache-clear. The reason for the build command 51 | is to guarantee your deployment is always being executed in the way you intended. Here's 52 | what the drush command essentially translates to. 53 | 54 | drush updatedb 55 | drush features-revert-all --force 56 | drush cc all 57 | 58 | But instead of of calling all those commands in the same order all the time you can now 59 | call _drush build --yes_. 60 | 61 | ####Devify 62 | During development you will periodically pull the staging or production database to your 63 | local environment. There is a list of commands and variables that you normally would 64 | alter such as disabling caches and Update module, sanitize emails and passwords and 65 | delete sensitive variables. The devify command takes a list of modules to disable/enable 66 | and a list of variables to delete/reset, plus it sanitizes the database. 67 | 68 | Devify is really effective when you set command-specific settings at drushrc.php, such 69 | as the following: 70 | 71 | /** 72 | * Settings for devify command. 73 | */ 74 | $command_specific['devify'] = array( 75 | 'enable-modules' => array('devel', 'advanced_help'), 76 | 'disable-modules' => array('varnish', 'memcache_admin'), 77 | 'delete-variables' => array('googleanalytics_account'), 78 | 'reset-variables' => array('site_mail' => 'local@local.com'), 79 | ); 80 | 81 | Then you would only need to type _drush devify --yes_. 82 | -------------------------------------------------------------------------------- /patches/readme.md: -------------------------------------------------------------------------------- 1 | #Patches 2 | 3 | Patch documentation should be in the following format: 4 | 5 | * module name 6 | * brief description 7 | * issue link (if exists) 8 | * patch file location 9 | 10 | Example: 11 | 12 | * views 13 | * Add CSS class to read-more link on trimmed text field 14 | * http://drupal.org/node/1557926 15 | * http://drupal.org/files/views-more_link_class-1557926.patch 16 | 17 | --- -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #Drupal Boilerplate# 2 | - 3 | 4 | Drupal boilerplate is not a module. Instead it just serves as a directory structure for 5 | starting a new drupal site. The idea behind Drupal boilerplate came from working on so many 6 | different sites which each follow their own development practice, directory structure, 7 | deployment guidelines, etc... 8 | 9 | Drupal boilerplate tries to simplify starting a new site by having the most common 10 | directory structures and files already included and set up. 11 | 12 | ##Getting started## 13 | You can start by [downloading](https://github.com/Lullabot/drupal-boilerplate/zipball/master) 14 | this project. Once you download it you will find that every folder contains a readme.md file. 15 | This readme.md file has been extensively documented to explain what belongs 16 | in that specific directory. 17 | 18 | Here's a breakdown for what each directory/file is used for. If you want to know more please 19 | read the readme inside the specific directory. 20 | 21 | * [docroot](https://github.com/Lullabot/drupal-boilerplate/tree/master/docroot) 22 | * Where your drupal root should start. 23 | * [drush](https://github.com/Lullabot/drupal-boilerplate/tree/master/drush) 24 | * Contains project specific drush commands, aliases, and configurations. 25 | * [results](https://github.com/Lullabot/drupal-boilerplate/tree/master/results) 26 | * This directory is just used to export test results to. A good example of this 27 | is when running drush test-run with the --xml option. You can export the xml 28 | to this directory for parsing by external tools. 29 | * [scripts](https://github.com/Lullabot/drupal-boilerplate/tree/master/scripts) 30 | * A directory for project-specific scripts. 31 | * [test](https://github.com/Lullabot/drupal-boilerplate/tree/master/test) 32 | * A directory for external tests. This is great for non drupal specific tests 33 | such as selenium, qunit, casperjs. 34 | * [.gitignore](https://github.com/Lullabot/drupal-boilerplate/blob/master/.gitignore) 35 | * Contains the a list of the most common excluded files. 36 | 37 | Built by Robots™ 38 | -------------------------------------------------------------------------------- /results/readme.md: -------------------------------------------------------------------------------- 1 | #Results 2 | - -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | Any custom project-specific scripts can be placed here. 2 | 3 | Any PHP scripts can be run by using the 4 | `$ drush scr ../scripts.foo.php` command from within the docroot directory. 5 | -------------------------------------------------------------------------------- /tests/create_content.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tests creating an article and viewing it. 3 | * 4 | * Requires the admin user account to be set at common.js in order 5 | * to log in. 6 | */ 7 | 8 | casper.test.begin("Test article workflow.", 5, function suite(test) { 9 | 10 | var sampleText = "Sample Article " + new Date().getTime(); 11 | var node_view_expression = /node\/([0-9]+)/i; 12 | var nid = 0; 13 | var node_links = []; 14 | var date = ''; 15 | var time = ''; 16 | 17 | // Returns administrative links within a node edit form. 18 | function nodeLinks() { 19 | var links = []; 20 | jQuery('.tabs.primary a').each(function () { 21 | links.push(jQuery(this).attr('href')); 22 | }); 23 | return links; 24 | } 25 | 26 | // Create an unpublished article. 27 | casper.boilerStartAs('admin'); 28 | casper.thenOpen('node/add/article', function() { 29 | test.assertHttpStatus(200, "Authenticated user can access the Create article form."); 30 | var params = { 31 | 'title' : sampleText, 32 | 'body[und][0][value]': 'The full text of ' + sampleText + '.' 33 | }; 34 | this.fill('.node-form', params, false); 35 | }); 36 | casper.thenEvaluate(function () { 37 | jQuery('input[name="status"]').trigger('click'); 38 | }); 39 | casper.thenClick('#edit-submit'); 40 | 41 | // Confirm article is created and capture nid. 42 | casper.waitForUrl(node_view_expression, function() { 43 | var matches = node_view_expression.exec(this.getCurrentUrl()); 44 | test.assertTruthy(matches[1], "Successfully created new article node: (nid " + matches[1] + ")"); 45 | nid = matches[1]; 46 | 47 | // Get the paths to this article. 48 | node_links = node_links.concat(this.evaluate(nodeLinks)); 49 | view = node_links[0]; 50 | view = view.slice(1); 51 | this.echo("The new article is viewable at the path " + view + "."); 52 | 53 | form = node_links[1]; 54 | form = form.slice(1); 55 | this.echo("The new article is edited at the path " + form + "."); 56 | 57 | // View the article as editor. 58 | casper.thenOpen(view, function() { 59 | test.assertTextExists(sampleText, "The new article " + sampleText + " is viewable to editor."); 60 | }); 61 | 62 | // Check that an anonymous user can't see an unpublished article. 63 | casper.boilerEndSession(); 64 | casper.thenOpen(view, function() { 65 | test.assertHttpStatus(403, "Anonymous users can't view unpublished content"); 66 | }); 67 | 68 | // Delete the article when testing is done. 69 | casper.boilerBeginSession('admin'); 70 | casper.thenOpen('node/' + nid + '/delete'); 71 | casper.thenClick('#edit-submit'); 72 | casper.then(function () { 73 | test.assertTextExists('has been deleted', "Sample article was deleted"); 74 | }); 75 | casper.boilerEndSession(); 76 | 77 | }); 78 | 79 | casper.boilerRun(); 80 | }); 81 | -------------------------------------------------------------------------------- /tests/homepage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Homepage tests. 3 | * 4 | * These tests make some assertions on a Drupal vanilla installation. 5 | * Feel free to change them to suit your needs. 6 | */ 7 | 8 | casper.test.begin('Tests homepage structure', 3, function suite(test) { 9 | // Open the homepage. 10 | casper.start(); 11 | casper.thenOpen('/', function() { 12 | // Check that we get a 200 response code. 13 | test.assertHttpStatus(200, 'Homepage was loaded successfully.'); 14 | // Check the presence of the main items in the page. 15 | test.assertExists('a#logo', 'Header link to the homepage is present.'); 16 | test.assertExists('form#user-login-form', 'Login form is present.'); 17 | }); 18 | 19 | casper.run(function() { 20 | test.done(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /tests/readme.md: -------------------------------------------------------------------------------- 1 | #Test 2 | ---- 3 | 4 | 5 | The test directory is used for external test. This is great for [selenium](http://seleniumhq.org/) or [CasperJS](http://casperjs.org/) test. 6 | 7 | There's two default directory. The selenium directory and the casperjs directory. Feel free to add or remove your own. 8 | 9 | Note: This is not a directory for simpletest. 10 | --------------------------------------------------------------------------------