Permalink
Browse files

Add tests for URL generation when creating a wall

  • Loading branch information...
1 parent 9091bcf commit 226a2de4ef3f93cb1d5ef761fc8891dd3981babe @birtles birtles committed Mar 19, 2013
@@ -36,6 +36,7 @@ CREATE TABLE `walls` (
`createDate` datetime NOT NULL COMMENT 'Creation datetime in UTC',
`modifyDate` datetime NOT NULL COMMENT 'Modification datetime in UTC',
PRIMARY KEY (`wallId`),
+ UNIQUE KEY (`urlPath`),
FOREIGN KEY (`designId`) REFERENCES `designs` (`designId`),
FOREIGN KEY (`owner`) REFERENCES `users` (`userId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Walls are shared drawing spaces';
View
@@ -0,0 +1,13 @@
+<?php
+/* vim: set syn=php: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Wide trim
+// Performs trim on a string but also strips full-width whitespace
+function wtrim($str) {
+ return preg_replace('/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $str);
+}
+
+?>
View
@@ -10,6 +10,7 @@ require_once("exceptions.inc");
require_once("UriUtils.inc");
require_once("designs.inc");
require_once("users.inc");
+require_once("utils.inc");
// When updating this, be sure to update login-controller.js as well
define("WALLMAKER_SESSION_NAME", "WMSESSID");
@@ -509,58 +510,97 @@ class Wall {
private $sessions = null;
private $email = null;
+ static private $hiddenFields = array('passcode');
+
public function __construct($id, $email, $metadata) {
$this->id = intval($id);
$this->email = trim($email);
$this->metadata = $metadata;
}
public function __get($name) {
- if ($name == 'passcode') {
+ // Check if the field is set (i.e. not hidden, not missing needed parameters
+ // etc.)
+ if (!isset($this->$name)) {
return null;
}
+ // Regular metadata
if (array_key_exists($name, $this->metadata)) {
return $this->metadata[$name];
}
- // Virtual: sessions
- // -- gets list of sessions and returns them
- // Virtual: design
- // -- does look up (using DesignGallery)
- // Virtual:
- // wallUrl = getCurrentServer() . '/wall/' . $this->metadata['urlPath'];
- // wallUrlShort = $this->metadata['shortUrl'];
- // editorUrl = $config['editor']['url'] . $this->metadata['urlPath'];
- // editorUrlShort = $this->metadata['editorShortUrl'];
- //
- // XXX Don't return the passcode, only the length of it
- // passcodeLen = @$this->metadata['passcode']
- // ? strlen($this->metadata['passcode'] : null;
+ // Virtual fields
+ switch ($name) {
+ case 'wallUrl':
+ return Wall::getUrlForPath($this->metadata['urlPath']);
+
+ case 'editorUrl':
+ return Wall::getEditorUrlForPath($this->metadata['urlPath']);
+
+ case 'passcodeLen':
+ return strlen($this->metadata['passcode']);
+ }
+
+ return null;
+ }
+
+ public function __isset($name) {
+ // Hidden fields
+ if (in_array($name, self::$hiddenFields))
+ return false;
+
+ // Regular metadata
+ if (array_key_exists($name, $this->metadata))
+ return true;
+
+ // Virtual fields
+ switch ($name) {
+ case 'wallUrl':
+ case 'editorUrl':
+ return isset($this->metadata['urlPath']);
+
+ case 'passcodeLen':
+ return isset($this->metadata['passcode']);
+ }
+
+ return false;
}
/*
public function __set($name) {
- // Check canWrite before doing anything
+ // Check canAdminister before doing anything
// Marks fields as dirty that have changed
}
*/
public function asArray() {
- return array(
- 'wallId' => $this->id,
- 'name' => $this->name,
- 'duration' => $this->duration,
- 'passcodeLen' => $this->passcodeLen
- );
+ // Fields to export if available
+ //
+ // Associative keys map the regular value name used by users of this class
+ // to another more export-friendly value.
+ $keys = array('id' => 'wallId', 'name',
+ 'wallUrl', 'wallShortUrl',
+ 'editorUrl', 'editorShortUrl',
+ 'duration', 'defaultDuration',
+ 'passcodeLen', 'latestSession');
+
+ $result = array();
+ foreach ($keys as $localKey => $keyToExport) {
+ $localKey = is_int($localKey) ? $keyToExport : $localKey;
+ if (isset($this->$localKey)) {
+ $result[$keyToExport] = $this->$localKey;
+ }
+ }
+ return $result;
}
public function startSession($sessionId, $datetime) {
// Sanitize input
$sessionId = toId($sessionId);
// Check authorisation
- if (!$this->canWrite()) {
+ if (!$this->canAdminister()) {
throw new KeyedException('no-auth');
}
@@ -590,6 +630,8 @@ class Wall {
}
$conn->disconnect();
+ // XXX Update latest session
+
return true;
}
@@ -598,7 +640,7 @@ class Wall {
$sessionId = toId($sessionId);
// Check authorisation
- if (!$this->canWrite()) {
+ if (!$this->canAdminister()) {
throw new KeyedException('no-auth');
}
@@ -609,7 +651,7 @@ class Wall {
return false;
}
- // Close session
+ // End session
$conn =& getDbConnection();
$query = 'UPDATE sessions'
. ' SET endDate=' . $conn->quote($datetime, 'timestamp')
@@ -621,18 +663,20 @@ class Wall {
}
$conn->disconnect();
+ // XXX Update latest session
+
// Return true since we made a change
return true;
}
public function save() {
- // Check canWrite
+ // Check canAdminister
}
public static function getPathForName($name) {
// Strip leading/trailing space, and
// convert fullwidth forms to halfwidth
- $path = mb_convert_kana(trim($name), "as", "utf-8");
+ $path = mb_convert_kana(wtrim($name), "as", "utf-8");
// Make lowercase, and
// convert whitespace to -
@@ -659,7 +703,7 @@ class Wall {
return $config['editor']['url'] . $path;
}
- protected function canWrite() {
+ protected function canAdminister() {
// In the future we will check if the wall has been shared with the current
// user or not
return $this->isOwner();
@@ -688,7 +732,7 @@ class Walls {
$ownerId = Users::getOrCreateFromEmail($email);
// Validate wall name
- $name = trim($name);
+ $name = wtrim($name);
if (!strlen($name)) {
error_log("Empty name");
throw new KeyedException('empty-name');
@@ -111,6 +111,11 @@ public function assertEqual($first, $second, $message = '%s') {
return self::$unitTestCase->assertEqual($first, $second, $message);
}
+ public function assertNotEqual($first, $second, $message = '%s') {
+ self::$unitTestCase->reporter = $this->reporter;
+ return self::$unitTestCase->assertNotEqual($first, $second, $message);
+ }
+
public function getConnection() {
return self::$conn;
}
@@ -20,7 +20,7 @@ function testLoggedOut() {
$this->testDesignId
);
$this->assertTrue(@$wall['error_key'] == 'logged-out',
- "Got wall whilst logged out.");
+ "Got wall whilst logged out");
}
function testCreate() {
@@ -43,34 +43,96 @@ function testCreate() {
function testName() {
$this->login();
- // Create wall
+ // Test same name is returned
$wall = $this->_createWall(
'Test wall',
$this->testDesignId
);
-
- // Test same name is returned
$this->assertEqual(@$wall['name'], 'Test wall');
-
- // Tidy up
$this->removeWall($wall['wallId']);
// Test non-ASCII name
+ $wall = $this->_createWall(
+ '素晴らしい壁',
+ $this->testDesignId
+ );
+ $this->assertEqual(@$wall['name'], '素晴らしい壁');
+ $this->removeWall($wall['wallId']);
+
// Test name is trimmed
+ $wall = $this->_createWall(
+ " \t space\r\n ",
+ $this->testDesignId
+ );
+ $this->assertEqual(@$wall['name'], 'space');
+ $this->removeWall($wall['wallId']);
+
// Test empty name is rejected
+ $wall = $this->_createWall("", $this->testDesignId);
+ $this->assertTrue(@$wall['error_key'] == 'empty-name',
+ "Made wall with no name");
+
// Test whitespace-only name is rejected
+ $wall = $this->_createWall(" \t\r\n ", $this->testDesignId);
+ $this->assertTrue(@$wall['error_key'] == 'empty-name',
+ "Made wall with whitespace name");
+
// Test duplicate name is rejected
+ $wallA = $this->_createWall('Test wall', $this->testDesignId);
+ $wallB = $this->_createWall(' Test wall ', $this->testDesignId);
+ $this->assertTrue(@$wallB['error_key'] == 'duplicate-name',
+ "Made two walls with the same name");
+ $this->removeWall($wallA['wallId']);
}
function testUrl() {
+ $this->login();
+
// Test simplification
+ $wall = $this->_createWall(' Test wall ', $this->testDesignId);
+ $this->assertEqual($this->getWallPath(@$wall['wallUrl']), 'test-wall');
+ $this->removeWall($wall['wallId']);
+
+ // Test non-ASCII
+ $wall = $this->_createWall('Café', $this->testDesignId);
+ $this->assertEqual($this->getWallPath(@$wall['wallUrl']), 'caf%C3%A9');
+ $this->removeWall($wall['wallId']);
+
+ // Test converting full-with numbers to half-width
+ $wall = $this->_createWall('123ABC ', $this->testDesignId);
+ $this->assertEqual($this->getWallPath(@$wall['wallUrl']), '123abc');
+ $this->removeWall($wall['wallId']);
+
// Test when simplification produces duplicates
+ // -- we should generate a random wall path instead
+ $wallA = $this->_createWall('ABC', $this->testDesignId);
+ $wallB = $this->_createWall('abc', $this->testDesignId);
+ $this->assertNotEqual($this->getWallPath(@$wallB['wallUrl']), 'abc');
+ $this->removeWall($wallA['wallId']);
+ $this->removeWall($wallB['wallId']);
+
// Test editor URL
- // Test short URLs
+ $wall = $this->_createWall('Test wall', $this->testDesignId);
+ $this->assertTrue(!empty($wall['editorUrl']), 'No editor URL found');
+ $this->removeWall($wall['wallId']);
+ }
+
+ function testEmail() {
+ // Test a bad email is rejected
+ // Test the ownerEmail returned is set to the email we passed in (after
+ // trimming)
}
function testDesignId() {
// Test it matches what we put in
+ // Test a bad ID fails
+ }
+
+ function getWallPath($wallUrl) {
+ // Convert http://...../wall-path/ => wall-path
+ if (!preg_match('/\/([^\/]*)$/', $wallUrl, $matches))
+ return null;
+ return $matches[1];
}
}
@@ -109,7 +109,7 @@ function _createWall($name, $designId) {
// Parse response
$wall = json_decode($response,true);
$this->assertTrue($wall !== null,
- "Failed to decode response: $response");
+ "Failed to decode response: " . str_replace('%', '%%', $response));
return $wall;
}

0 comments on commit 226a2de

Please sign in to comment.