Much has been said about last month's highly critical Drupal security issue 'SA-CORE-2014-005', otherwise known as 'Drupalgeddon'. It was covered by mainstream international media, even if the reaction needs addressing. Drupal's security team take a responsible approach to security issues - being open & honest in disclosing them with fixes, in keeping with the community values. Security issues should always be expected in any software, it's how they are dealt with that speaks far more.
We patched all the sites that we had access to immediately fix, and informed all our clients of the issue as soon as possible. If you host a Drupal site, and haven't yet, run through the Drupalgeddon workflow right now.
To complete my series on multilingual Drupal, here are some mini-lessons I've learnt. Some of them are are to improve the experience for administrators & translators, others cover obscure corners of code. The first few don't require any knowledge of code, but the later ones will be much more technical.
Content (node-level) translation or entity (field-level) translation?
It seems an obvious question to ask, but what are you translating?
The tools exist to translate just about anything in Drupal 7*, but in many different ways, so you need to know exactly what you're translating. Language is 'a first-class citizen', in the sense that any piece of text is inherently written by someone on some language, which Drupal 7 is built to recognise. Sometimes you want to translate each & every individual piece of text (e.g. at the sentence or paragraph level). Other times you want to translate a whole page or section that is made up of multiple pieces of text.
mouse.click and mouse.move are a really helpfuls function in CasperJS, but we have at times found that they just don't work. Mostly, that's been because the element isn't there to click on. Do make sure that it's actually there! Make sure you're using the right selector, too. Try a casper.capture() to see whether it's there, but be wary of timings to ensure that you get a capture for the moment that you want to be performing the mouse action.
Part 6: Manually fail a test, but continue script execution
We set up an event to take screenshots of failed test pages, by hooking into the onFail event. This made for a problem when we wanted to pass or fail a test based on whether there were entries in the Drupal Watchdog table. Failing a test also would normally stop script execution, but we explicitly need our post script to finish its work!
As I described previously, we nicely externalised our list of viewport sizes, making it really easy to set our viewports for mobile, tablet and desktop tests. Our content appearance tests put this to good use, taking screenshots of the content at mobile, tablet and desktop resolutions. The problem we very quickly ran into was that we frequently ended up with empty screenshots, or sometimes no screenshot at all. This is where the asynchronous fun began.
Two fonts walk into the bar, and the barman says, “Sorry lads, we don’t serve your type.”
It was a good day. I'd finished writing up the basic appearance tests for the first batch of content types, I'd road-tested them on my machine, we'd set up Jenkins… all was ready to go for our first run on the server. When we ran it, however, all the tests failed against the baseline.
Part 3: Using other scripts, datasources and directories
Earlier I described a bit about the scope of the project and how careful planning would be needed to keep the project growing smoothly. One result of this is our test template - a basic test script outline which most scripts should stick to - which makes test scripts easier to update because they all follow the same structure (yay standardisation!).