@@ -1,119 +1,171 @@
$(function () {
"use strict";

$("#create_account").click(function () {
$('#new_user_box').modal('show');
});
$(function () {

$("#forgot_pw").click(function () {
$('#forgotten_pw_box').modal('show');
});
$("#create_account").click(createAccountClick);

$("button[name='cancel']").click(function () {
$('#new_user_box').modal('hide');
});
$("#forgot_pw").click(forgotPWClick);

$("button[name='btnLogin']").click(function () {
console.log("click click motherfucker")
$.ajax({
url: 'login',
type: 'POST',
data: {
'login': $("input[name='input_login']").val(),
'pw': $("input[name='input_pw']").val()
},
success: function (data) {
if (data) {
console.log(data);
}
else {
window.location.replace("/")
}
}
});
});
$("button[name='cancel-add']").click(cancelAddClick);

$("button[name='save_user']").click(function () {
$.ajax({
url: 'save_new_user',
type: 'POST',
data: {'email1':$("input[name='email_input_1']").val(),
'email2':$("input[name='email_input_1']").val(),
'pw1':$("input[name='pw_input_1']").val(),
'pw2': $("input[name='pw_input_2']").val(),
'shipname': $("input[name='ship_input']").val()
},
success: function(data) {
if (data) {
console.log(data);
}
else {
window.location.replace("/")
}
}
});
});
$("button[name='pw_cancel']").click(cancelAddClick);

$("#new_user_box").on('hidden.bs.modal', function (e) {

});
$("button[name='btnLogin']").click(loginClick);

$("input[name='email_input_1']").blur(function () {
$.ajax({
url: 'validate/email',
type: 'POST',
data: { 'email': $("input[name='email_input_1']").val() },
success: function (data) {
if (data) {
$('.validation_success').addClass("hidden");
$(data).removeClass("hidden");
}
else {
$('.validation_success').removeClass("hidden");
$('.email_error').addClass("hidden");
}
}
});
});
$("button[name='save_user']").click(saveUserClick);

$("input[name='email_input_2']").blur(function () {
if ($("input[name='email_input_1']").val() != $("input[name='email_input_2']").val()) {
$("#mismatched_email").removeClass("hidden");
}
else {
$("#mismatched_email").addClass("hidden");
}
});
$("#new_user_box").on('hidden.bs.modal', onNewUserModalHide);

$("input[name='pw_input_1']").blur(function () {
if ($("input[name='pw_input_1']").val().length < 6) {
$("#short_pw").removeClass("hidden");
}
else {
$("#short_pw").addClass("hidden");
}
});
$("input[name='email_input_1']").blur(onEmail1InputBlur);

$("input[name='pw_input_2']").blur(function () {
if ($("input[name='pw_input_1']").val() != $("input[name='pw_input_2']").val()) {
$("#mismatched_pw").removeClass("hidden");
}
else {
$("#mismatched_pw").addClass("hidden");
}
});
$("input[name='email_input_2']").blur(onEmail2InputBlur);


$("input[name='pw_input_1']").blur(onPw1InputBlur);

$("input[name='pw_input_2']").blur(onPw2InputBlur);

});

function ValidateInputsMatch(matchClass, caseSensitive) {
var dotMatchClass = "." + matchClass
if ($(dotMatchClass).length == 0) {
throw new RangeError("There are no elements with class " + matchClass);
}
var firstValue = $(dotMatchClass).first().val();
var loopValue = firstValue;
if (!caseSensitive) {
firstValue = firstValue.toLowerCase();
}
var isMatch = true;
$(dotMatchClass).each(function () {
loopValue = $(this).val();
if (!caseSensitive) {
loopValue = loopValue.toLowerCase();
}
if (firstValue != loopValue) {
isMatch = false;
return isMatch;
}
});
return isMatch;
}

function clearNewAccountWindow() {
$("input[name='email_input_1']").val("");
$("#email_validation").html("");
$(".validation_message").addClass("hidden");
$("input[name='email_input_2']").val("");
$("input[name='pw_input_1']").val("");
$("#pw_validation").html("");
$("input[name='pw_input_2']").val("");
$("input[name='ship_input']").val("");
}


function createAccountClick() {
$('#new_user_box').modal('show');
}

function forgotPWClick() {
$('#forgotten_pw_box').modal('show');
}

function cancelAddClick() {
$('#new_user_box').modal('hide');
}

function cancelForgotPassword() {
$('#forgotten_pw_box').modal('hide');
}

function loginClick() {
$.ajax({
url: 'login',
type: 'POST',
data: {
'login': $("input[name='input_login']").val(),
'pw': $("input[name='login_pw']").val()
},
success: loginAjaxSuccess
});
}

function saveUserClick() {
$.ajax({
url: 'save_new_user',
type: 'POST',
data: {
'email1': $("input[name='email_input_1']").val(),
'email2': $("input[name='email_input_1']").val(),
'pw1': $("input[name='pw_input_1']").val(),
'pw2': $("input[name='pw_input_2']").val(),
'shipName': $("input[name='ship_input']").val()
},
success: loginAjaxSuccess
});
}

function onNewUserModalHide() {
clearNewAccountWindow();
}

function onEmail1InputBlur() {
$.ajax({
url: 'validate/email',
type: 'POST',
data: { 'email': $("input[name='email_input_1']").val() },
success: validateNewEmailAjaxSuccess
});
}

function onEmail2InputBlur() {
if (ValidateInputsMatch("match_email")) {
$("#mismatched_email").addClass("hidden");
}else {
$("#mismatched_email").removeClass("hidden");
}
}

function onPw1InputBlur() {
if ($("input[name='pw_input_1']").val().length < 6) {
$("#short_pw").removeClass("hidden");
}
else {
$("#short_pw").addClass("hidden");
}
}

function onPw2InputBlur() {

if (ValidateInputsMatch("match_pw",true)) {
$("#mismatched_pw").addClass("hidden");
}
else {
$("#mismatched_pw").removeClass("hidden");
}
}

function validateNewEmailAjaxSuccess(data) {
if (data) {
$('.validation_success').addClass("hidden");
$(data).removeClass("hidden");
}
else {
$('.validation_success').removeClass("hidden");
$('.email_error').addClass("hidden");
}
}

function loginAjaxSuccess(data) {

$(".login_error").addClass("hidden");

if (data['success']) {
window.location.replace("/")
}
else {
var errors = data['errors'];
for(var i = 0; i < errors.length; i++){
$(errors[i]).removeClass("hidden");
}
}
}

@@ -1,19 +1,19 @@
$(function(){

$.ajax({
url: "/hero",
type: 'get',
dataType: 'json',
error: function (p1,p2,p3) {
alert(p3);
},
success: function (data) {
heroFromJson = JSON.parse(data);
//$.ajax({
// url: "/hero",
// type: 'get',
// dataType: 'json',
// error: function (p1,p2,p3) {
// //alert(p3);
// },
// success: function (data) {
// //heroFromJson = JSON.parse(data);


ko.applyBindings(new SpaceHabitModel(heroFromJson));
}
});
// //ko.applyBindings(new SpaceHabitModel(heroFromJson));
// }
//});

function clearDailyEditInputs(){
$('#edit_daily_box input').val("");
@@ -3,56 +3,214 @@
import Account
import Hero
import re
import cherrypy
import EverywhereConstants as consts

"""
This module contains all that methods that determine if user provided details
are correct.
"""


def is_login_taken(login):
return UserDBLayer.does_login_exist(login)


def insert_new_user(login,pw,shipName = ""):
"""
This used during the create new user process
saves a new user to the database
args:
login:
unique email address supplied by the user
pw:
password supplied by the user.
shipName:
The space ship name is supplied by the user.
Not required but lame if not there.
returns:
a tuple containing the primary key of the newly inserted user from the
User table, the primary key of the account created for the new user,
and the primary key of the hero created for the new user.
"""
if is_login_taken(login):
raise FileExistsError("That email is already taken")
id = safe_insert_new_user(login,pw)
accountId = Account.create_new_account(id)
heroId = Hero.create_new_hero(accountId,shipName)
return (id,accountId,heroId)


def get_existing_user_details(login):
"""
"""
userid = UserDBLayer.get_user(login)
#accountId = Account.Account(


def safe_insert_new_user(login,pw):
cryptPair = get_new_user_encrypted_details(pw)
safePw = cryptPair[0]
salt = cryptPair[1]
id = UserDBLayer.insert_user(login,safePw,salt)
"""
This used during the create new user process.
this should be called when doing the actual inserting of a new user.
This encrypts the password before saving.
args:
login:
unique email address supplied by the user
pw:
the unencrypted password supplied by the user.
returns:
the primary key returned from the Database upon insertion of
the new user
"""
safePw = CryptKeeper.encrypt_str(pw)
id = UserDBLayer.insert_user(login,safePw)
return id

def get_new_user_encrypted_details(pw):
salt = CryptKeeper.pass_the_salt()
safePw = CryptKeeper.encrypt_str(pw,salt)
return (safePw,salt)

def authenticate_user(login,pw):
"""
This is used during the login process.
Determines if the user is trying to log on with a valid login and
also determines if the user is trying to log on with a correct password
args:
login:
email address supplied by the user
pw:
the unencrypted password supplied by the user.
returns:
a dict with two keys, a boolean: 'success' and list: 'errors.'
'success' tells the caller whether or not the login attempt was successful.
If it was 'success' is true, then 'errors' should be an empty list.
If 'success' is false, then 'errors' will have between one
and two elements. Each of them will be id-css selectors for jquery
to use.
"""
user = UserDBLayer.get_user(login)
resultDict = {'messages':[],'success':False}
if not user:
return (False,"#bad_login")
resultDict['messages'].append("#bad_login")
return resultDict
if not CryptKeeper.password_is_right(pw,user[UserDBLayer.USER_PASSWORD]):
return (False, "#bad_login_pw")
return (True,"")
resultDict['messages'].append("#bad_login_pw")
return resultDict
resultDict['success'] = True
return resultDict


def validate_email(email):
"""
This used during the create new user process.
determines if the email supplied is formatted correctly and doesn't
already exist.
args:
email:
An email address supplied by the user
returns:
a dict with two keys, a boolean: 'success' and list: 'errors.'
'success' tells the caller whether or not the login attempt was successful.
If it was 'success' is true, then 'errors' should be an empty list.
If 'success' is false, then 'errors' will have between one
and two elements. Each of them will be id-css selectors for jquery
to use.
"""
if not re.match(r"[^@]+@[^@]+\.[^@]+",email):
return "#bad_email"
return {'success': False,'messages':["#bad_email"]}
if UserDBLayer.does_login_exist(email):
return "#taken_email"
return ""

def validate_everything_new_user(email1,email2,pw1,pw2):
emailErrors = []
pwErrors = []
emailValidationResult = validate_email(email1)
if emailValidationResult:
emailErrors.append(emailValidationResult)
if email1 != email2:
emailErrors.append("#mismatched_email")
if len(pw1) < 6:
pwErrors.append("#short_pw")
if pw1 != pw2:
pwErrors.append("#mismatched_pw")
return (emailErrors,pwErrors)
return {'success': False,'messages':["#taken_email"]}
return {'success': True,'messages':["#good_email"]}


def check_all_new_user_validations(email1,email2,pw1,pw2,shipName):
"""
This used during the create new user process.
This method calls other validation methods and baically determines
if any of the info that the user entered was illegal.
args:
all args should be strings and less than 256 characters else
this will return invalid.
email1:
this should be input that will also pass the
validate_email test
email2:
this should match email1.
pw1:
this only needs to pass any password complexity requirements
that have been added to the method. Currently the only
requirement is that the password must be at least 6
characters.
pw2:
this should match pw1:
returns:
a list of violations that either the user's email or password
commits. An empty list implies that everything is dandy.
"""
flags = []
if len(email1) <= 256:
emailValidationResult = validate_email(email1)
if not emailValidationResult['success']:
flags.extend( emailValidationResult['errors'])
if email1 != email2:
flags.append( "#mismatched_email")
else:
if len(email1) > 256:
flags.append("#email1_too_long")
if len(email2) > 256:
flags.append("#email2_too_long")
if len(pw1) <= 256:
if len(pw1) < 6:
flags.append("#short_pw")
if pw1 != pw2:
flags.append("#mismatched_pw")
else:
if len(pw1) > 256:
flags.append("pw1_too_long")
if len(pw2) > 256:
flags.append("pw2_too_long")
if len(shipName) > 256:
flags.append("#shipname_too_long")
return flags

#disableAuthenticationRedirects should only ever be used in testing.
#Never in production
disableAuthenticationRedirects = False

def redirect_unauthenticated():
"""
a cherrypy decororator. Place the decorator infront of controller
methods that return parts of the website which the user needs to be
logged in to see. If they are not logged in, redirect them to the
login page.
"""
if disableAuthenticationRedirects:
return
username = cherrypy.session.get(consts.SESSION_KEY)
if not username:
raise cherrypy.HTTPRedirect("/login")

def redirect_authenticated():
"""
a cherrypy decororator. Place the decorator infront of controller
methods that return the login part of the website.
If they are already logged in, redirect them to the main page.
"""
if disableAuthenticationRedirects:
return
username = cherrypy.session.get(consts.SESSION_KEY)
if username:
raise cherrypy.HTTPRedirect("/")

#These are useable as soon as I import AuthenticationLayer
cherrypy.tools.redirect_unauthenticated = cherrypy.Tool("before_handler",redirect_unauthenticated)
cherrypy.tools.redirect_authenticated = cherrypy.Tool("before_handler",redirect_authenticated)
@@ -1,5 +1,9 @@
import configparser

"""
this is a wrapper for reading from the config.ini file.
"""

config = configparser.ConfigParser()
config.read('config.ini')

@@ -9,19 +13,28 @@ def get_is_debug():
def get_access_key():
key = config['DEFAULT']['AWS_ACCESS_KEY_ID']
return key


def get_secret_key():
return config['DEFAULT']['AWS_SECRET_ACCESS_KEY']


def get_region():
return config['DEFAULT']['REGION']


def get_port():
if get_is_debug():
return config['DEBUG']['PORT']
return config['DEFAULT']['PORT']


def get_url():
if get_is_debug():
return config['DEBUG']['URL']
return config['DEFAULT']['URL']


def get_authentication_server():
if get_is_debug():
return config['DEBUG']['AUTHENTICATION_URL']
@@ -1,13 +1,39 @@
import uuid
from passlib.hash import pbkdf2_sha256

"""
This module is a wrapper for encryption methods.
"""

def pass_the_salt():
return uuid.uuid4().hex
def encrypt_str(str):

def encrypt_str(str,salt = None):
"""
This is a wrapper method for encrypting passwords
args:
str: this should be a string. This will be the password you want
to encrypt
returns:
the pbkdf2_sha256 encrypted version of str, the salt and other
useful information is built into it.
"""
hash = pbkdf2_sha256.encrypt(str)
return hash

def password_is_right(str,hash,salt = None):
def password_is_right(str,hash):
"""
wrapper to method that checks a password against the saved encrypted
password
args:
str: password sent by the user. We're checking to see if
it's the right one
hash: the encrypted version of the password that was saved in the
database
returns:
true or false: true if the str matches the hash, false if not.
"""
return pbkdf2_sha256.verify(str,hash)
@@ -2,37 +2,101 @@
from pymongo import MongoClient
import pymongo


"""
This is a wrapper for interaction with the database. Each of these methods
can be overridden to connect to a different db.
"""

connection = None

def get_open_connection():
"""
wrappper around the opening of the connection to the db
"""
return MongoClient(ConfigLayer.get_url(), int(ConfigLayer.get_port()))


def open_conn():
"""
Checks if there is already an open db connection. If not then it opens
one. Either way, it returns the open db connection.
"""
global connection
if connection is None:
connection = get_open_connection()
return connection


def get_table(tableName):
"""
gets the dataset associated with the given name.
args:
tableName:
name of the dataset that is wanted by the caller
def get_table(tablename):
returns:
a dataset upon which futher inquries can be done.
"""
open_conn()
db = connection.spacehabit
return db[tablename]
return db[tableName]


def get_thing_by_id(id,tableName):
"""
This is a wrapper method to get a single item from the database that
is associated with the given id.
args:
id:
this is a primary key for an item in the database
tableName:
this is the name of the dataset that is expected to have
the item we're looking for.
returns:
a dict with an _id field that matches id
"""
collection = get_table(tableName)
return collection.find_one({'_id':id})


def insert_thing(stuff, tableName):
"""
this is a wrapper method for inserting an item into the db
args:
stuff:
this will be a dict. Ideally this will have most of the
same properties that the rest of the items in this dataset has.
tableName:
this is the name of the dataset that we're inserting
our item into.
returns:
the primary key of the newly inserted item.
"""
collection = get_table(tableName)
id = collection.insert_one(stuff).inserted_id
return id


def update_thing_by_id(id,tableName,changes):
"""
This is a wrapper method for updating a single item in our db.
args:
id:
this is a primary key for an item in the database
tableName:
this is the name of the dataset that is expected to have
the item we're looking for.
changes:
this will be a dict. Each field in this dict will have a value
that overwrites the old value for that field for that item
in the db
"""
collection = get_table(tableName)
collection.update(
{'_id': id},
@@ -43,9 +107,75 @@ def update_thing_by_id(id,tableName,changes):


def delete_thing_by_key(key,tableName):
"""
Removes a particular item from the database
args:
key:
primary key of the item that we want to remove from the db
tableName:
name of the dataSet that has the item that we want to remove
"""
collection = get_table(tableName)
collection.remove({'_id':key})

def get_sorted_stuff_by_key(seachForDict,tableName,sortByList):
def get_sorted_stuff_by_search(searchForDict,tableName,sortByList = None,limit=10000):
"""
gets a collection of items from the database that matches a given
search criteria and then sorts it by some fields given to it
args:
searchForDict:
this will be a dict of what to search the database for.
To be returned by this method, the item in the database
must have contain all of the keys in searchForDict and
paired values must also match.
Read the mongoDB tutorial on find for clarification.
tableName:
name of the dataset that we are getting items from
sortByList:
this will be a list of tuples.
Each tuple in the list, must have two values. The first is the
name of the field that we are sorting by. The second value is
either 1 or -1(pymongo.ASCINDING, pyongo.DESCINDING)
This will tell the database to sort the values in increasing
or decreasing order.
limit:
this is the maximum number of records to return
returns:
Right now, this returns some sort of mongoDB collection, but I am
going to change this to return a wrapper object with skip and limit
methods.
"""
collection = get_table(tableName)
findResult = collection.find(searchForDict)
if sortByList:
return findResult.sort(sortByList).limit(limit)
else:
return findResult.limit(limit)


def get_count_of_stuff_search(searchForDict,tableName):
"""
This is a wrapper method for getting the count of items in a particular
dataset.
args:
searchForDict:
this will be a dict of what to search the database for.
To be counted by this method, the item in the database
must have contain all of the keys in searchForDict and
paired values must also match.
Read the mongoDB tutorial on find for clarification.
tableName:
name of the dataset that we are counting items from
returns:
The count of items from our given dataset and that meet our
conditions
"""
collection = get_table(tableName)
return collection.find(seachForDict).sort(sortByList)
return collection.find(searchForDict).count()
@@ -1,23 +1,40 @@
from Daily import Daily
from Habit import Habit
from Todo import Todo
from Good import Good
from collections import OrderedDict


class Heap(object):


class Heap(object):
"""
This is a standard heap object for sorting. This is not needed for the
actual application but is nevertheless used for testing purposes.
"""
def __init__(self, sortByFunction):
"""
args:
sortByFunction:
needs to be a lamba that that can be used to
compare the values of two items in the heap
"""
self._heap = []
self._sortByFunction = sortByFunction


def is_empty(self):
return len(self._heap) == 0


def __len__(self):
return len(self._heap)


def push(self,item):
"""
Adds items to the sorting heap to be sorted.
args:
item type should be consistent with whatever type you've
already been put in the heap otherwise, you're gonna
have a bad time.
"""
self._heap.append(item)
i = len(self._heap) -1
parent = (i -1) // 2
@@ -31,6 +48,14 @@ def push(self,item):


def pop(self):
"""
Standard sorting heap pop method. Get's the next item based on
sort order and then removes that item from the heap.
returns:
the next item in order. You know what you added to this. I don't.
If there are no more items, this throws an error.
"""
if len(self._heap) == 0:
raise IndexError("You tried to pop from an empty heap")
topItem = self._heap[0]
@@ -52,24 +77,64 @@ def pop(self):
i2 = 2*i +2
return topItem


def push_list(self,list):
"""
push a whole list onto the sorting heap to be sorted.
args:
list:
this should be a list or at least some sort of iterable object.
Idealy, all of the items in this list should also be the
same type but that's your fucking problem.
"""
for i in list:
self.push(i)


def get_sorted_list(self):
"""
Get's a sorted list.
The heap will be empty after you call this and if you try to
call it again, it will thrown an error because it's empty.
returns:
a sorted list of whatever you put in here.
"""
sorted = []
while len(self._heap) > 0:
sorted.append(self.pop())
return sorted


def popper(self):
"""
this is a generator to get items off of the sort heap in order.
This is useful when you don't want to get all of the items at once
or when you want to distribute work load between different calls.
yields:
the item next in the sort order.
throws an error in the heap is empty.
"""
while len(self._heap) > 0:
yield self.pop()


def top(self):
"""
returns:
get the next item in order from the heap without removing it.
"""
return self._heap[0]


def clear(self):
"""
removes all items from the heap
"""

self._heap.clear()


@@ -7,33 +7,43 @@
USER_LOGIN = 'login'
USER_PASSWORD = 'pw'
USER_SALT = 'salt'
USER_DESC = 'desc'

connection = None

def get_connection():
"""
wrappper around the opening of the connection to the db
"""
return MongoClient(ConfigLayer.get_authentication_server(), int(ConfigLayer.get_port()))


def open_conn():
"""
Checks if there is already an open db connection. If not then it opens
one. Either way, it returns the open db connection.
"""
global connection
if connection is None:
connection = get_connection()


def get_user_collection():
open_conn()
db = connection.spacehabit
return db[COLLECTION_NAME]

def get_user(login):
return get_user_collection().find_one({USER_LOGIN:login})
return get_user_collection().find_one({USER_LOGIN:login.lower()})

def does_login_exist(login):
if get_user_collection().find({USER_LOGIN:login}).count() > 0:
if get_user_collection().find({USER_LOGIN:login.lower()}).count() > 0:
return True
else:
return False

def insert_user(login,pw,salt):
id = get_user_collection().insert_one({USER_LOGIN:login,
def insert_user(login,pw):
id = get_user_collection().insert_one({USER_LOGIN:login.lower(),
USER_PASSWORD:pw,
USER_SALT:salt}).inserted_id
USER_DESC: login}).inserted_id
return id
@@ -6,7 +6,7 @@
<ProjectGuid>60383a39-fa97-4e70-a3b7-20aa3969670b</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>Web Server\SpaceHabitServer.py</StartupFile>
<SearchPath>CoreGame\;HabitFrontend\;Helpers\;Story\;Tests\;Types\;Web Server\;Web Server\Controllers\;Tests\TestHelpers\</SearchPath>
<SearchPath>CoreGame\;HabitFrontend\;Helpers\;Story\;Tests\;Types\;Web Server\;Web Server\Controllers\;Tests\TestHelpers\;Tests\ForCoreGame\;Tests\ForHelpers\;Tests\ForTestHelpers\;Tests\ForTypes\;Tests\JSTests\</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>SpaceHabitRPG</Name>
@@ -55,6 +55,12 @@
<Folder Include="Story\" />
<Folder Include="Story\__pycache__\" />
<Folder Include="Tests\" />
<Folder Include="Tests\Frontend\" />
<Folder Include="Tests\JSTests\" />
<Folder Include="Tests\ForHelpers\" />
<Folder Include="Tests\ForTypes\" />
<Folder Include="Tests\ForCoreGame\" />
<Folder Include="Tests\ForTestHelpers\" />
<Folder Include="Tests\TestHelpers\" />
<Folder Include="Tests\__pycache__\" />
<Folder Include="Types\" />
@@ -82,6 +88,7 @@
<Content Include="HabitFrontend\public\login.js" />
<Content Include="HabitFrontend\public\script.js" />
<Content Include="HabitFrontend\public\style.css" />
<Content Include="HabitFrontend\TestPlayground.html" />
<Content Include="Helpers\__pycache__\ConfigLayer.cpython-35.pyc" />
<Content Include="Helpers\__pycache__\DatabaseLayer.cpython-35.pyc" />
<Content Include="Helpers\__pycache__\Heap.cpython-35.pyc" />
@@ -116,6 +123,9 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Helpers\DatabaseLayer.py" />
<Compile Include="Helpers\DataPaginator.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Helpers\EverywhereConstants.py">
<SubType>Code</SubType>
</Compile>
@@ -129,34 +139,79 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Story\ZoneLookup.py" />
<Compile Include="Tests\AuthenticationLayerTests.py">
<Compile Include="Tests\ForCoreGame\Test_Progression.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForHelpers\Test_AuthenticationLayer.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForHelpers\Test_DatabaseLayer.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForHelpers\Test_DataPaginator.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForHelpers\Test_Heap.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForTestHelpers\Test_MockDatabaseLayer.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForTestHelpers\Test_MockDataLoader.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForTestHelpers\Test_SpaceUnitTest.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForTestHelpers\Test_TestFunctionBuilder.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ForTypes\Test_Daily.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\LoginPageTest.py">
<Compile Include="Tests\ForTypes\Test_Hero.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\MockDataLoaderTests.py">
<Compile Include="Tests\Frontend\LoginPageNewUserTests.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\Frontend\LoginPageOnLoadTest.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\Frontend\LoginPageRequests.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\Frontend\LoginSaveNewUser.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\Frontend\PlaygroundLoad.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\JSTests\LoginJSTest.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\JSTests\PlaygroundLoginJS.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\TestHelpers\MockDatabaseLayer.py" />
<Compile Include="Tests\ProgressionTests.py" />
<Compile Include="Tests\TestHelpers\MockDataLoader.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\TestHelpers\MockSetUp.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\TestHelpers\TestDummyObjectMaker.py">
<Compile Include="Tests\TestHelpers\SeleniumHelper.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\TestHelpers\TestFunctionBuilder.py">
<Compile Include="Tests\TestHelpers\SpaceUnitTest.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\TestHelpers\TestDummyObjectMaker.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\TestToolsTest.py">
<Compile Include="Tests\TestHelpers\TestFunctionBuilder.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tests\ToolsTests.py" />
<Compile Include="Tests\TypesTests.py" />
<Compile Include="Types\Account.py" />
<Compile Include="Types\Daily.py" />
<Compile Include="Types\Good.py" />
@@ -167,9 +222,6 @@
<Compile Include="Types\Zone.py" />
<Compile Include="Web Server\Controllers\AccountController.py" />
<Compile Include="Web Server\Controllers\AllDailiesController.py" />
<Compile Include="Web Server\Controllers\AuthenticationController.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="Web Server\Controllers\HeroController.py" />
<Compile Include="Web Server\Controllers\LoginController.py" />
<Compile Include="Web Server\Controllers\ValidationController.py">

This file was deleted.

@@ -1,9 +1,9 @@
import unittest
from SpaceUnitTest import SpaceUnitTest
import Progression
from collections import OrderedDict


class Test_ProgressionTests(unittest.TestCase):
class Test_Progression(SpaceUnitTest):

def test_convert_number_to_naming_number_base(self):
n = Progression.convert_number_to_naming_number_base(0,10)
@@ -131,3 +131,4 @@ def test_get_unlocked_zones(self):

if __name__ == '__main__':
unittest.main()

@@ -0,0 +1,95 @@
from SpaceUnitTest import SpaceUnitTest
import DatabaseLayer
import UserDBLayer
import MockDatabaseLayer
import AuthenticationLayer as auth

class Test_AuthenticationLayerTests(SpaceUnitTest):

@classmethod
def setUpClass(cls):
import MockSetUp
MockSetUp.set_up_mock_db_connections()
return super().setUpClass()

def tearDown(self):
MockDatabaseLayer.clean_up()
return super().tearDown()

def test_insert_new_user(self):
result = auth.insert_new_user("a@b.c","p","s")
self.assertEqual(result[0],MockDatabaseLayer.users+"0")
self.assertEqual(result[1],MockDatabaseLayer.accounts+"1")
self.assertEqual(result[2],MockDatabaseLayer.heros+"2")

def test_is_login_taken(self):
t = auth.is_login_taken("a@b.c")
self.assertFalse(t)
auth.insert_new_user("b@c.d","p","s")
t = auth.is_login_taken("b@c.d")
self.assertTrue(t)

def test_authenticate_user(self):
auth.insert_new_user("c@d.e","p","s")
result = auth.authenticate_user("d@e.f","")
self.assertEqual(len(result['errors']),1)
self.assertEqual(result['errors'][0],"#bad_login")
result = auth.authenticate_user("c@d.e","123")
self.assertEqual(len(result['errors']),1)
self.assertEqual(result['errors'][0],"#bad_login_pw")
result = auth.authenticate_user("c@d.e","p")
self.assertEqual(len(result['errors']),0)
self.assertTrue(result['success'])

def test_validate_email(self):
auth.insert_new_user("a@b.c","p","s")
t = auth.validate_email("@@")
self.assertFalse(t['success'])
self.assertEqual(t['messages'][0],"#bad_email")
t = auth.validate_email("a@b.c")
self.assertFalse(t['success'])
self.assertEqual(t['messages'][0],"#taken_email")
t = auth.validate_email("b@c.d")
self.assertTrue(t['success'])
self.assertEqual(t['messages'][0],"#good_email")

def test_validate_everything_new_user_bad_email(self):
t = auth.check_all_new_user_validations("bademail","bademail","123456","123456","ship")
self.assertEqual(len(t),1)
self.assertEqual(t[0],"#bad_email")


def test_validate_everything_new_user_bad_mismatched_email(self):
t = auth.check_all_new_user_validations("bademail","verybademail","123456","123456","ship")
self.assertEqual(len(t),2)
self.assertIn("#bad_email",t)
self.assertIn("#mismatched_email",t)

def test_validate_everything_new_user_bad_pw(self):
t = auth.check_all_new_user_validations("bademail","verybademail","123","123","ship")
self.assertEqual(len(t),3)
self.assertIn("#bad_email",t)
self.assertIn("#mismatched_email",t)
self.assertIn("#short_pw",t)


def test_validate_everything_new_user_bad_mismatched_pw(self):
t = auth.check_all_new_user_validations("bademail","verybademail","123","abc","ship")
self.assertEqual(len(t),4)
self.assertIn("#bad_email",t)
self.assertIn("#mismatched_email",t)
self.assertIn("#short_pw",t)
self.assertIn("#mismatched_pw",t)


def test_validate_everything_good_user_pw(self):
t = auth.check_all_new_user_validations("a@b.c","a@b.c","123456","123456","ship")
self.assertEqual(len(t),0)


def test_safe_insert_new_user(self):
id = auth.safe_insert_new_user("a","123")
self.assertEqual(id,"users0")

if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,41 @@
from SpaceUnitTest import SpaceUnitTest
from bson.objectid import ObjectId
from Account import COLLECTION_NAME as accounts
from Daily import COLLECTION_NAME as dailiesName
import random
import DatabaseLayer

class Test_Test_DatabaseLayer(SpaceUnitTest):
def setUp(self):
self.accountCount0 = DatabaseLayer.get_count_of_stuff_search({},accounts)
self.dailiesCount0 = DatabaseLayer.get_count_of_stuff_search({},dailiesName)
self.accountId = DatabaseLayer.insert_thing({'test':0},accounts)
testList = []
self.controlList = []
for i in range(0,500):
u = i // 100
r = (500 -i) // 25
f = i
tObj = {'ownerAccountId':self.accountId,'daysUntilTrigger':u,'urgency':r,'difficulty':f,'isCompleted':False}
testList.append(tObj)
self.controlList.append(tObj)
random.shuffle(testList)

for d in testList:
id = DatabaseLayer.insert_thing(d,dailiesName)
print(id)
print("done")
return super().setUp()

def tearDown(self):
dailyCollection = DatabaseLayer.get_table(dailiesName)
result = dailyCollection.delete_many( {'ownerAccountId':self.accountId})
DatabaseLayer.delete_thing_by_key(self.accountId,accounts)
accountCount1 = DatabaseLayer.get_count_of_stuff_search({},accounts)
dailiesCount1 = DatabaseLayer.get_count_of_stuff_search({},dailiesName)
self.assertEqual(accountCount1,self.accountCount0)
self.assertEqual(dailiesCount1,self.dailiesCount0)
return super().tearDown()

if __name__ == '__main__':
unittest.main()
@@ -1,39 +1,29 @@
import unittest
from Heap import Heap
from SpaceUnitTest import SpaceUnitTest
from collections import OrderedDict
import random
import DatabaseLayer
from bson.objectid import ObjectId
from TestDummyObjectMaker import DailySortingTestObject
from Account import COLLECTION_NAME as accounts
from Daily import COLLECTION_NAME as dailiesName


class Test_ToolsTests(unittest.TestCase):


from Heap import Heap
import random

class Test_Heap(SpaceUnitTest):

def setUp(self):
self.accountId = DatabaseLayer.insert_thing({'test':0},accounts)
testList = []

self.testList = []
self.controlList = []
for i in range(0,500):
u = i // 100
r = (500 -i) // 25
f = i
tObj = {'ownerAccountId':self.accountId,'daysUntilTrigger':u,'urgency':r,'difficulty':f,'isCompleted':False}
testList.append(tObj)
random.shuffle(testList)
tObj = DailySortingTestObject(u,r,f)
self.testList.append(tObj)
self.controlList.append(tObj)
random.shuffle(self.testList)

for d in testList:
id = DatabaseLayer.insert_thing(d,dailiesName)
print(id)
print("done")
return super().setUp()

def tearDown(self):
dailyCollection = DatabaseLayer.get_table(dailiesName)
result = dailyCollection.delete_many( {'ownerAccountId':self.accountId})
DatabaseLayer.delete_thing_by_key(self.accountId,accounts)

return super().tearDown()

def test_heap_basic_functions(self):
@@ -89,35 +79,11 @@ def test_heapsort(self):
def test_multifield_heapsort(self):
heap = Heap(lambda a,b: a.daysUntilTrigger <= b.daysUntilTrigger
and a.urgency >= b.urgency and a.difficulty <= b.difficulty)
controlList = []
for i in range(0,500):
u = i // 100
r = (500 -i) // 25
f = i
controlList.append(DailySortingTestObject(u,r,f))
testList = controlList[:]
random.shuffle(testList)
heap.push_list(testList)
for a,c in zip(heap.popper(),controlList):
heap.push_list(self.testList)
for a,c in zip(heap.popper(),self.controlList):
self.assertEqual(a.daysUntilTrigger,c.daysUntilTrigger)
self.assertEqual(a.urgency,c.urgency)
self.assertEqual(a.difficulty,c.difficulty)

def test_db_daily_sorting(self):
import Daily
controlList = []
for i in range(0,500):
u = i // 100
r = (500 -i) // 25
f = i
controlList.append(DailySortingTestObject(u,r,f))
dailies = Daily.get_dailies_by_account(self.accountId)
for d,c in zip(dailies,controlList):
self.assertEqual(d['daysUntilTrigger'],c.daysUntilTrigger)
self.assertEqual(d['urgency'],c.urgency)
self.assertEqual(d['difficulty'],c.difficulty)



if __name__ == '__main__':
unittest.main()
unittest.main()
@@ -0,0 +1,36 @@
from SpaceUnitTest import SpaceUnitTest
import MockDatabaseLayer
import MockDataLoader
import EverywhereConstants

class Test_MockDataLoader(SpaceUnitTest):
def test_insert_one_user(self):
idStuff = MockDataLoader.insert_one_user()
self.assertEqual(idStuff[EverywhereConstants.ID_KEY],"users0")
self.assertEqual(idStuff[MockDatabaseLayer.USER_LOGIN],"a@b.c")
self.assertEqual(len(idStuff[MockDatabaseLayer.USER_PASSWORD]),87)
self.assertEqual(len(idStuff[MockDatabaseLayer.USER_SALT]),32)
stuff = MockDatabaseLayer.get_thing_by_id(idStuff[EverywhereConstants.ID_KEY],MockDatabaseLayer.users)
self.assertTrue(MockDatabaseLayer.USER_PASSWORD in stuff)
self.assertTrue(MockDatabaseLayer.USER_LOGIN in stuff)
self.assertTrue(MockDatabaseLayer.USER_SALT in stuff)
login = stuff[MockDatabaseLayer.USER_LOGIN]
self.assertEqual(login,"a@b.c")
pw = stuff[MockDatabaseLayer.USER_PASSWORD]
self.assertEqual(len(pw),87)
salt = stuff[MockDatabaseLayer.USER_SALT]
self.assertEqual(len(salt),32)


def test_insert_user_mixed_case(self):
MockDatabaseLayer.insert_user("A@B.C","123","salt")
stuff = MockDatabaseLayer.get_user("a@b.c")
self.assertIsNotNone(stuff)
self.assertIn(MockDatabaseLayer.USER_DESC, stuff)
desc = stuff[MockDatabaseLayer.USER_DESC]
self.assertEqual(desc,"A@B.C")
login = stuff[MockDatabaseLayer.USER_LOGIN]
self.assertEqual(login, "a@b.c")

if __name__ == '__main__':
unittest.main()
@@ -1,37 +1,8 @@
from SpaceUnitTest import SpaceUnitTest
import MockDatabaseLayer
import TestFunctionBuilder
import unittest
import random

class Test_TestToolsTest(unittest.TestCase):

def test_build_sort_function_single_property(self):
dictDict = {}
dictDict[10] = {'a':0}
dictDict[11] = {'a':1}
dictDict[12] = {'a':2}
compareFieldList = [('a',1)]
comparer = TestFunctionBuilder.build_sort_by_function(compareFieldList,dictDict)
t = comparer(dictDict[10],dictDict[11])
self.assertTrue(t)
t = comparer(dictDict[11],dictDict[10])
self.assertFalse(t)
t = comparer(dictDict[10],dictDict[10])
self.assertTrue(t)

def test_build_sort_function_double_property(self):
dictDict = {}
for i in range(0,15):
dictDict[10 + i] = {'a':i % 5, 'b': 15-i}
compareFieldList = [('a',1),('b',-1)]
comparer = TestFunctionBuilder.build_sort_by_function(compareFieldList,dictDict)
t = comparer(dictDict[10],dictDict[20])
self.assertTrue(t)
t = comparer(dictDict[10],dictDict[11])
self.assertTrue(t)
t = comparer(dictDict[10],dictDict[24])
self.assertTrue(t)

class Test_MockDatabaseLayer(SpaceUnitTest):
def test_insert_and_get_from_mock_db(self):
t1 = {'a':121,'b':235,'c':316}
id = MockDatabaseLayer.insert_thing(t1,MockDatabaseLayer.dailies)
@@ -97,5 +68,24 @@ def test_get_sorted_stuff_by_key(self):
self.assertEqual(s['b'],c['b'])
self.assertEqual(s['c'],c['c'])


def test_unfiltered_mockdb_count(self):
for i in range(0,100):
MockDatabaseLayer.insert_thing({'a':i,'b':i % 5},MockDatabaseLayer.dailies)
count = MockDatabaseLayer.get_count_of_stuff_search({},MockDatabaseLayer.dailies)
self.assertEqual(count,100)

def test_filtered_mockdb_count_multi(self):
for i in range(0,100):
MockDatabaseLayer.insert_thing({'a':i,'b':i % 5,'c':i %10},MockDatabaseLayer.dailies)
count = MockDatabaseLayer.get_count_of_stuff_search({'b':1, 'c':1},MockDatabaseLayer.dailies)
self.assertEqual(count,10)

def test_filtered_mockdb_count(self):
for i in range(0,100):
MockDatabaseLayer.insert_thing({'a':i,'b':i % 5},MockDatabaseLayer.dailies)
count = MockDatabaseLayer.get_count_of_stuff_search({'b':1},MockDatabaseLayer.dailies)
self.assertEqual(count,20)

if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,13 @@
from SpaceUnitTest import SpaceUnitTest

class Test_SpaceUnitTest(SpaceUnitTest):
def test_assertBool(self):
t1 = None
t2 = 6
self.assertRaises(AssertionError, lambda :self.assertFalse(t1))
self.assertRaises(AssertionError, lambda :self.assertTrue(t2))
self.assertNotEqual(t1,False)
self.assertNotEqual(t2,True)

if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,34 @@
from SpaceUnitTest import SpaceUnitTest
import TestFunctionBuilder

class Test_TestFunctionBuilder(SpaceUnitTest):
def test_build_sort_function_single_property(self):
dictDict = {}
dictDict[10] = {'a':0}
dictDict[11] = {'a':1}
dictDict[12] = {'a':2}
compareFieldList = [('a',1)]
comparer = TestFunctionBuilder.build_sort_by_function(compareFieldList,dictDict)
t = comparer(dictDict[10],dictDict[11])
self.assertTrue(t)
t = comparer(dictDict[11],dictDict[10])
self.assertFalse(t)
t = comparer(dictDict[10],dictDict[10])
self.assertTrue(t)

def test_build_sort_function_double_property(self):
dictDict = {}
for i in range(0,15):
dictDict[10 + i] = {'a':i % 5, 'b': 15-i}
compareFieldList = [('a',1),('b',-1)]
comparer = TestFunctionBuilder.build_sort_by_function(compareFieldList,dictDict)
t = comparer(dictDict[10],dictDict[20])
self.assertTrue(t)
t = comparer(dictDict[10],dictDict[11])
self.assertTrue(t)
t = comparer(dictDict[10],dictDict[24])
self.assertTrue(t)


if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,53 @@
from SpaceUnitTest import SpaceUnitTest
from Account import COLLECTION_NAME as TABLE_ACCOUNT
from Daily import COLLECTION_NAME as TABLE_DAILIES
import DatabaseLayer
import random


class Test_Daily(SpaceUnitTest):

def setUp(self):
self.accountCount0 = DatabaseLayer.get_count_of_stuff_search({},TABLE_ACCOUNT)
self.dailiesCount0 = DatabaseLayer.get_count_of_stuff_search({},TABLE_DAILIES)
self.accountId = DatabaseLayer.insert_thing({'test':0},TABLE_ACCOUNT)
testList = []
self.controlList = []
for i in range(0,500):
u = i // 100
r = (500 -i) // 25
f = i
tObj = {'ownerAccountId':self.accountId,'daysUntilTrigger':u,'urgency':r,'difficulty':f,'isCompleted':False}
testList.append(tObj)
self.controlList.append(tObj)
random.shuffle(testList)

for d in testList:
id = DatabaseLayer.insert_thing(d,TABLE_DAILIES)
print(id)
print("done")
return super().setUp()

def tearDown(self):
dailyCollection = DatabaseLayer.get_table(TABLE_DAILIES)
result = dailyCollection.delete_many( {'ownerAccountId':self.accountId})
DatabaseLayer.delete_thing_by_key(self.accountId,TABLE_ACCOUNT)
accountCount1 = DatabaseLayer.get_count_of_stuff_search({},TABLE_ACCOUNT)
dailiesCount1 = DatabaseLayer.get_count_of_stuff_search({},TABLE_DAILIES)
self.assertEqual(accountCount1,self.accountCount0)
self.assertEqual(dailiesCount1,self.dailiesCount0)
return super().tearDown()




def test_db_daily_sorting(self):
import Daily
dailies = Daily.get_dailies_by_account(self.accountId)
for d,c in zip(dailies,self.controlList):
self.assertEqual(d['daysUntilTrigger'],c.daysUntilTrigger)
self.assertEqual(d['urgency'],c.urgency)
self.assertEqual(d['difficulty'],c.difficulty)

if __name__ == '__main__':
unittest.main()
@@ -1,10 +1,10 @@
import unittest
from SpaceUnitTest import SpaceUnitTest
import DatabaseLayer
import MockDatabaseLayer
from Hero import Hero
from Hero import create_new_hero

class Test_TypesTests(unittest.TestCase):
class Test_Hero(SpaceUnitTest):
def setUp(self):
DatabaseLayer.insert_thing = MockDatabaseLayer.insert_thing
DatabaseLayer.get_thing_by_id = MockDatabaseLayer.get_thing_by_id
@@ -1,15 +1,16 @@
import unittest
from SpaceUnitTest import SpaceUnitTest
import SpaceHabitServer
import MockSetUp
import threading
import cherrypy
import time
from selenium import webdriver
import requests
import MockDataLoader
import MockDatabaseLayer
import SeleniumHelper



class Test_LoginPageTest(unittest.TestCase):
class Test_LoginPageNewUserTests(SpaceUnitTest):

@classmethod
def setUpClass(cls):
@@ -36,124 +37,212 @@ def tearDownClass(cls):
return super().tearDownClass()

def setUp(self):
self.driver = webdriver.PhantomJS()
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(5)
self.driver.get("http://127.0.0.1:8080")
self.open_new_user_box()
self.input1 = self.driver.find_element_by_xpath("//input[@name='email_input_1']")
self.input2 = self.driver.find_element_by_xpath("//input[@name='email_input_2']")
self.pw1 = self.driver.find_element_by_xpath("//input[@name='pw_input_1']")
self.pw2 = self.driver.find_element_by_xpath("//input[@name='pw_input_2']")
self.modal = self.driver.find_element_by_id("new_user_box")
return super().setUp()


def tearDown(self):
import MockDatabaseLayer
MockDatabaseLayer.clean_up()
self.driver.quit()
return super().tearDown()

def test_initial_page_is_login(self):
self.assertEqual(self.driver.current_url,"http://127.0.0.1:8080/login/")
self.assertEqual(self.driver.title,"Login to Space Habit Frontier")

def test_login_page_default_state(self):
print(self.driver.page_source)
elem = self.driver.find_element_by_id("bad_login")
self.assertFalse(elem.is_displayed())
elem = self.driver.find_element_by_id("bad_login_pw")
self.assertFalse(elem.is_displayed())
elem = self.driver.find_element_by_id("new_user_box")
self.assertFalse(elem.is_displayed())
elem = self.driver.find_element_by_id("forgotten_pw_box")
self.assertFalse(elem.is_displayed())

def open_new_user_box(self):
clickElem = self.driver.find_element_by_id("create_account")
clickElem.click()

def test_create_user_model_validation_is_clean(self):
self.open_new_user_box()
elem = self.driver.find_element_by_id("new_user_box")

def test_bad_email(self):
self.input1.send_keys("aaaa")
self.modal.click()

elem = self.driver.find_element_by_id("bad_email")
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())


def test_taken_email(self):
MockDataLoader.insert_one_user()
self.input1.send_keys("a@b.c")
self.modal.click()

elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())

def insert_user(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"a@b.c",'pw1':"123456",'pw2':"123456",'shipName':"USS Enterprise"})
self.assertEqual(r.status_code,200)

def test_send_user_params_success(self):
self.insert_user()
def test_good_email(self):
self.input1.send_keys("a@b.c")
self.modal.click()

elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

def test_insert_user_bad_params(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"a@b.c",'pw1':"123456",'pw2':"123456"})
self.assertEqual(r.status_code,404)
elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())


def test_mismatched_email(self):
self.input1.send_keys("a@b.c")
self.input2.send_keys("b@c.d")
self.modal.click()

def test_new_user_bad_email(self):
self.open_new_user_box()
typeElem = self.driver.find_element_by_xpath("//input[@name='email_input_1']")
typeElem.send_keys("aaaa")
clickElem = self.driver.find_element_by_xpath("//input[@name='email_input_2']")
clickElem.click()
elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())


def test_bad_pw(self):
self.pw1.click()
self.pw1.send_keys("123")

self.modal.click()
elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())

def test_taken_email(self):
self.insert_user()
self.open_new_user_box()
typeElem = self.driver.find_element_by_xpath("//input[@name='email_input_1']")
typeElem.send_keys("a@b.c")
clickElem = self.driver.find_element_by_xpath("//input[@name='email_input_2']")
clickElem.click()
def test_mismatch_pw(self):
self.pw1.send_keys("123456")

self.pw2.send_keys("abcded")
self.modal.click()

elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertTrue(elem.is_displayed())


def test_bad_then_good_email(self):
self.input1.send_keys("aaaa")
self.modal.click()

elem = self.driver.find_element_by_id("bad_email")
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())

def test_incomplete_user_good_email(self):
print(self.driver.page_source)
self.open_new_user_box()
typeElem = self.driver.find_element_by_xpath("//input[@name='email_input_1']")
typeElem.send_keys("a@b.c")
clickElem = self.driver.find_element_by_xpath("//input[@name='email_input_2']")
clickElem.click()
self.input1.send_keys("a@b.c")
self.modal.click()

elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())

@@ -0,0 +1,101 @@
from SpaceUnitTest import SpaceUnitTest
import SpaceHabitServer
import MockSetUp
import threading
import cherrypy
import time
from selenium import webdriver
import SeleniumHelper
import requests
import MockDataLoader



class Test_LoginPageTest(SpaceUnitTest):

@classmethod
def setUpClass(cls):
MockSetUp.set_up_mock_db_connections()
cls.server = SpaceHabitServer.HabitServer()
cls.server.start()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STARTED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().setUpClass()

@classmethod
def tearDownClass(cls):
cls.server.stop()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STOPPED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().tearDownClass()

def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(5)
self.driver.get("http://127.0.0.1:8080")
return super().setUp()

def tearDown(self):
import MockDatabaseLayer
MockDatabaseLayer.clean_up()
self.driver.quit()
return super().tearDown()

def test_initial_page_is_login(self):
self.assertEqual(self.driver.current_url,"http://127.0.0.1:8080/login/")
self.assertEqual(self.driver.title,"Login to Space Habit Frontier")

def test_login_page_default_state(self):
elem = self.driver.find_element_by_id("bad_login")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("bad_login_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("new_user_box")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("forgotten_pw_box")
self.assertFalse(elem.is_displayed())

def open_new_user_box(self):
clickElem = self.driver.find_element_by_id("create_account")
clickElem.click()

def test_create_user_model_validation_is_clean(self):
self.open_new_user_box()
elem = self.driver.find_element_by_id("new_user_box")
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())





if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,113 @@
from SpaceUnitTest import SpaceUnitTest
import SpaceHabitServer
import MockSetUp
import threading
import cherrypy
import time
import requests
import MockDataLoader
import MockDatabaseLayer
import json


class Test_LoginSaveNewUserWithRequests(SpaceUnitTest):

@classmethod
def setUpClass(cls):
MockSetUp.set_up_mock_db_connections()
cls.server = SpaceHabitServer.HabitServer()
cls.server.start()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STARTED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().setUpClass()

@classmethod
def tearDownClass(cls):
cls.server.stop()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STOPPED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().tearDownClass()

def tearDown(self):
import MockDatabaseLayer
MockDatabaseLayer.clean_up()
return super().tearDown()

def test_send_success(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"a@b.c",'pw1':"123456",'pw2':"123456",'shipName':"USS Enterprise"})
self.assertEqual(r.status_code,200)
data = json.loads(r.text)
self.assertEqual(data['success'], True)


def test_insert_user_missing_param(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"a@b.c",'pw1':"123456",'pw2':"123456"})
self.assertEqual(r.status_code,404)


def test_send_missing_input2_pw1_pw2(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"",'pw1':"",'pw2':"",'shipName':""})
self.assertEqual(r.status_code,200)
data = json.loads(r.text)
self.assertEqual(data['success'], False)


def test_send_missing_pw(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"a@b.c",'pw1':"",'pw2':"",'shipName':""})
self.assertEqual(r.status_code,200)
data = json.loads(r.text)
self.assertEqual(data['success'], False)


def test_send_taken_email(self):
MockDataLoader.insert_one_user()
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"a@b.c",'pw1':"123456",'pw2':"123456",'shipName':""})
self.assertEqual(r.status_code,200)
data = json.loads(r.text)
self.assertEqual(data['success'], False)

def test_send_mismatched_email(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"b@c.d",'pw1':"123456",'pw2':"123456",'shipName':""})
self.assertEqual(r.status_code,200)
data = json.loads(r.text)
self.assertEqual(data['success'], False)

def test_send_bad_pw(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"b@c.d",'pw1':"123",'pw2':"123",'shipName':""})
self.assertEqual(r.status_code,200)
data = json.loads(r.text)
self.assertEqual(data['success'], False)

def test_send_mismatched_pw(self):
s = requests.Session()
r = s.post("http://127.0.0.1:8080/login/save_new_user/",params={'email1':"a@b.c",
'email2':"b@c.d",'pw1':"123456",'pw2':"abcdef",'shipName':""})
self.assertEqual(r.status_code,200)
data = json.loads(r.text)
self.assertEqual(data['success'], False)


if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,92 @@
from SpaceUnitTest import SpaceUnitTest
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import SpaceHabitServer
import MockSetUp
import threading
import cherrypy
import time
import requests
import MockDataLoader
import MockDatabaseLayer
import SeleniumHelper


class Test_LoginSaveNewUser(SpaceUnitTest):

@classmethod
def setUpClass(cls):
MockSetUp.set_up_mock_db_connections()
cls.server = SpaceHabitServer.HabitServer()
cls.server.start()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STARTED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().setUpClass()

@classmethod
def tearDownClass(cls):
cls.server.stop()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STOPPED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().tearDownClass()

def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(5)
self.driver.get("http://127.0.0.1:8080")
self.input1 = self.driver.find_element_by_xpath("//input[@name='email_input_1']")
self.input2 = self.driver.find_element_by_xpath("//input[@name='email_input_2']")
self.pw1 = self.driver.find_element_by_xpath("//input[@name='pw_input_1']")
self.pw2 = self.driver.find_element_by_xpath("//input[@name='pw_input_2']")
self.modal = self.driver.find_element_by_id("new_user_box")
self.loginEmail = self.driver.find_element_by_xpath("//input[@name='input_login']")
self.loginPw = self.driver.find_element_by_xpath("//input[@name='login_pw']")
self.loginButton = self.driver.find_element_by_xpath("//button[@name='btnLogin']")
return super().setUp()


def tearDown(self):
import MockDatabaseLayer
MockDatabaseLayer.clean_up()
self.driver.quit()
return super().tearDown()


def open_new_user_box(self):
clickElem = self.driver.find_element_by_id("create_account")
clickElem.click()

def test_create_new_user(self):
self.open_new_user_box()
self.input1.send_keys("a@b.c")
self.input2.send_keys("a@b.c")
self.pw1.send_keys("123456")
self.pw2.send_keys("123456")
self.driver.find_element_by_xpath("//button[@name='save_user']").click()
WebDriverWait(self.driver,10).until(EC.title_is("Space Habit Frontier!"))
self.assertEqual(self.driver.title,"Space Habit Frontier!")

def test_login(self):
from selenium.common.exceptions import TimeoutException
MockDataLoader.insert_one_user()
self.loginEmail.send_keys("a@b.c")
self.loginPw.send_keys("123456")
self.loginButton.click()
WebDriverWait(self.driver,10).until(EC.title_is("Space Habit Frontier!"))
self.assertEqual(self.driver.title,"Space Habit Frontier!")
self.driver.get("http://127.0.0.1:8080/login")
self.assertRaises(TimeoutException,lambda :WebDriverWait(self.driver,5).until(EC.title_is("Login to Space Habit Frontier")))



if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,48 @@
from SpaceUnitTest import SpaceUnitTest
import SpaceHabitServer
import MockSetUp
import threading
import cherrypy
import time
from selenium import webdriver
import requests
import MockDataLoader
import MockDatabaseLayer
import SeleniumHelper

class Test_PlaygroundLoad(SpaceUnitTest):

@classmethod
def setUpClass(cls):
MockSetUp.set_up_mock_db_connections()
cls.server = SpaceHabitServer.HabitServer()
cls.server.start()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STARTED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().setUpClass()

@classmethod
def tearDownClass(cls):
cls.server.stop()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STOPPED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().tearDownClass()


def test_load(self):
driver = webdriver.Firefox()
driver.implicitly_wait(5)
driver.get("http://127.0.0.1:8080/playground")
self.assertEqual(driver.title,"Test Playground")
driver.quit()

if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,211 @@
from SpaceUnitTest import SpaceUnitTest
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import SpaceHabitServer
import MockSetUp
import threading
import cherrypy
import time
import requests
import MockDataLoader
import MockDatabaseLayer
import AuthenticationLayer

class Test_LoginJSTest(SpaceUnitTest):

@classmethod
def setUpClass(cls):
MockSetUp.set_up_mock_db_connections()
cls.server = SpaceHabitServer.HabitServer()
cls.server.start()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STARTED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().setUpClass()

@classmethod
def tearDownClass(cls):
cls.server.stop()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STOPPED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().tearDownClass()

def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(5)
self.driver.get("http://127.0.0.1:8080")
self.input1 = self.driver.find_element_by_xpath("//input[@name='email_input_1']")
self.input2 = self.driver.find_element_by_xpath("//input[@name='email_input_2']")
self.pw1 = self.driver.find_element_by_xpath("//input[@name='pw_input_1']")
self.pw2 = self.driver.find_element_by_xpath("//input[@name='pw_input_2']")
self.ship = self.driver.find_element_by_xpath("//input[@name='ship_input']")
self.newUserModal = self.driver.find_element_by_id("new_user_box")
self.pwModal = self.driver.find_element_by_id("forgotten_pw_box")
return super().setUp()

def tearDown(self):
import MockDatabaseLayer
MockDatabaseLayer.clean_up()
self.driver.quit()
return super().tearDown()

def open_new_user_box(self):
clickElem = self.driver.find_element_by_id("create_account")
clickElem.click()

def test_clearNewAccountWindow(self):
self.open_new_user_box()
self.input1.send_keys("aaaaa")
self.input2.send_keys("bbbbb")
self.pw1.send_keys("cccc")
self.pw2.send_keys("dddd")
self.ship.send_keys("eeee")
self.driver.execute_script("clearNewAccountWindow();")
self.assertEqual(self.input1.get_attribute('value'),"")
self.assertEqual(self.input2.get_attribute('value'),"")
self.assertEqual(self.pw1.get_attribute('value'),"")
self.assertEqual(self.pw2.get_attribute('value'),"")
self.assertEqual(self.ship.get_attribute('value'),"")

elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("short_pw")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("mismatched_pw")
self.assertFalse(elem.is_displayed())


def test_createAccountClick(self):
elem = self.driver.find_element_by_id("new_user_box")
self.assertFalse(elem.is_displayed())
self.driver.execute_script("createAccountClick();")
self.assertTrue(elem.is_displayed())


def test_forgotPWClick(self):
self.assertFalse(self.pwModal.is_displayed())
self.driver.execute_script("forgotPWClick();")
self.assertTrue(self.pwModal.is_displayed())


def test_cancelAddClick(self):
self.open_new_user_box()
self.assertTrue(self.newUserModal.is_displayed())
self.driver.execute_script("cancelAddClick();")
self.assertFalse(self.newUserModal.is_displayed())


def test_cancelForgotPassword(self):
self.driver.find_element_by_id("forgot_pw").click()
self.assertTrue(self.pwModal.is_displayed())
self.driver.execute_script("cancelForgotPassword();")
self.assertFalse(self.pwModal.is_displayed())


def test_validateEmailAjaxSuccess(self):
self.open_new_user_box()
self.driver.execute_script("validateNewEmailAjaxSuccess('#bad_email');")

elem = self.driver.find_element_by_id("bad_email")
self.assertTrue(elem.is_displayed())

self.driver.execute_script("validateNewEmailAjaxSuccess('#taken_email');")

elem = self.driver.find_element_by_id("bad_email")
self.assertTrue(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertTrue(elem.is_displayed())

self.driver.execute_script("validateNewEmailAjaxSuccess('');")

elem = self.driver.find_element_by_id("bad_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("taken_email")
self.assertFalse(elem.is_displayed())

elem = self.driver.find_element_by_id("good_email")
self.assertTrue(elem.is_displayed())

def test_loginAjaxSuccessSession(self):
AuthenticationLayer.disableAuthenticationRedirects = True
self.driver.execute_script("loginAjaxSuccess({'errors':[\"#bad_login\",\"#bad_login_pw\"],'success':false});")

self.assertEqual(self.driver.title,"Login to Space Habit Frontier")
elem = self.driver.find_element_by_id("bad_login")
self.assertTrue(elem.is_displayed())
elem = self.driver.find_element_by_id("bad_login_pw")
self.assertTrue(elem.is_displayed())

self.driver.execute_script("loginAjaxSuccess({'errors':[\"#bad_login_pw\"],'success':false});")

self.assertEqual(self.driver.title,"Login to Space Habit Frontier")
elem = self.driver.find_element_by_id("bad_login")
self.assertFalse(elem.is_displayed())
elem = self.driver.find_element_by_id("bad_login_pw")
self.assertTrue(elem.is_displayed())

self.driver.execute_script("loginAjaxSuccess({'errors':[],'success':true});")
#WebDriverWait(self.driver,10).until(EC.title_is("Space Habit Frontier!"))
self.assertEqual(self.driver.title,"Space Habit Frontier!")

def test_onEmail2InputBlur(self):
self.open_new_user_box()
self.input1.send_keys("a@b.c")
self.input2.send_keys("b@c.d")
self.driver.execute_script("onEmail2InputBlur();")
elem = self.driver.find_element_by_id("mismatched_email")
self.assertTrue(elem.is_displayed())
self.input2.clear()
self.input2.send_keys("a@b.c")
self.assertEqual(self.input1.get_attribute('value'),self.input2.get_attribute('value'))
self.driver.execute_script("onEmail2InputBlur();")
self.assertFalse(elem.is_displayed())

def test_onPw1InputBlur(self):
self.open_new_user_box()
self.pw1.send_keys("123")
self.driver.execute_script("onPw1InputBlur();")
elem = self.driver.find_element_by_id("short_pw")
self.assertTrue(elem.is_displayed())
self.pw1.clear()
self.pw1.send_keys("123456")
self.driver.execute_script("onPw1InputBlur();")
self.assertFalse(elem.is_displayed())

def test_onPw2InputBlur(self):
self.open_new_user_box()
self.pw1.send_keys("abcdef")
self.pw2.send_keys("Abcdef")
self.driver.execute_script("onPw2InputBlur();")
elem = self.driver.find_element_by_id("mismatched_pw")
self.assertTrue(elem.is_displayed())
self.pw2.clear()
self.pw2.send_keys("abcdef")
self.assertEqual(self.pw1.get_attribute('value'),self.pw2.get_attribute('value'))
self.driver.execute_script("onPw2InputBlur();")
self.assertFalse(elem.is_displayed())


if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,108 @@
from SpaceUnitTest import SpaceUnitTest
import SpaceHabitServer
import MockSetUp
import threading
import cherrypy
import time
from selenium import webdriver
import requests
import MockDataLoader
import MockDatabaseLayer
import SeleniumHelper

class Test_PlaygroundLoginJS(SpaceUnitTest):

@classmethod
def setUpClass(cls):
MockSetUp.set_up_mock_db_connections()
cls.server = SpaceHabitServer.HabitServer()
cls.server.start()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STARTED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().setUpClass()

@classmethod
def tearDownClass(cls):
cls.server.stop()
ticks = 0
while cherrypy.engine.state != cherrypy.engine.states.STOPPED:
time.sleep(1)
ticks += 1
if ticks >= 10:
raise TimeoutError("ran out of time")
return super().tearDownClass()

def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(5)
self.driver.get("http://127.0.0.1:8080/playground")
self.input1 = self.driver.find_element_by_xpath("//input[@name='input1']")
self.input2 = self.driver.find_element_by_xpath("//input[@name='input2']")
self.input3 = self.driver.find_element_by_xpath("//input[@name='input3']")
self.email1 = self.driver.find_element_by_xpath("//input[@name='email_input_1']")
self.email2 = self.driver.find_element_by_xpath("//input[@name='email_input_2']")
self.pw1 = self.driver.find_element_by_xpath("//input[@name='pw_input_1']")
self.pw2 = self.driver.find_element_by_xpath("//input[@name='pw_input_2']")
self.ship = self.driver.find_element_by_xpath("//input[@name='ship_input']")
return super().setUp()

def tearDown(self):
import MockDatabaseLayer
MockDatabaseLayer.clean_up()
self.driver.quit()
return super().tearDown()

def test_match(self):
self.input1.send_keys("abcdefg")
self.input2.send_keys("abcdefg")
self.input3.send_keys("abcdefg")
r = self.driver.execute_script("return ValidateInputsMatch('match');")
self.assertTrue(r)

def test_match_two(self):
self.email1.send_keys("abcdefg")
self.email2.send_keys("abcdefg")
r = self.driver.execute_script("return ValidateInputsMatch('match_email');")
self.assertTrue(r)

def test_mismatch_two(self):
self.email1.send_keys("abcdefg")
self.email2.send_keys("abcd")
r = self.driver.execute_script("return ValidateInputsMatch('match_email');")
self.assertFalse(r)

def test_mismatch_first(self):
self.input1.send_keys("abcdefi")
self.input2.send_keys("abcdefg")
self.input3.send_keys("abcdefg")
r = self.driver.execute_script("return ValidateInputsMatch('match');")
self.assertFalse(r)

def test_mismatch_last(self):
self.input1.send_keys("abcdefg")
self.input2.send_keys("abcdefg")
self.input3.send_keys("abcdefj")
r = self.driver.execute_script("return ValidateInputsMatch('match');")
self.assertFalse(r)

def test_match_empty(self):
from selenium.common.exceptions import WebDriverException
self.assertRaises(WebDriverException,lambda :self.driver.execute_script("return ValidateInputsMatch('empty');"))


def test_caseSensitivity(self):
self.input1.send_keys("abcdefg")
self.input2.send_keys("Abcdefg")
self.input3.send_keys("abcdefg")
r = self.driver.execute_script("return ValidateInputsMatch('match',true);")
self.assertFalse(r)
r = self.driver.execute_script("return ValidateInputsMatch('match');")
self.assertTrue(r)


if __name__ == '__main__':
unittest.main()

This file was deleted.

@@ -0,0 +1,27 @@
class MockDBResult(object):
"""
This will be used with the mock version of get_sorted_stuff_by_search.
It's basically a mock mongodb cursor
"""

def __init__(self,data):
"""
args:
data:
this should be a list of dicts. Doesn't really matter
what's in those dicts
"""
self._data = data

def next(self):
"""
this is a generator function that gets the next item in the list
yieds:
a dict containing dummy data most likely
"""
for d in self._data:
yield d


@@ -1,7 +1,9 @@
import MockDatabaseLayer
import AuthenticationLayer
import EverywhereConstants

def insert_one_user():
cryptPair = AuthenticationLayer.get_new_user_encrypted_details("123456")
id = MockDatabaseLayer.insert_user("a@b.c",cryptPair[0],cryptPair[1])
return id
return {EverywhereConstants.ID_KEY:id,MockDatabaseLayer.USER_LOGIN:"a@b.c",
MockDatabaseLayer.USER_PASSWORD:cryptPair[0],MockDatabaseLayer.USER_SALT:cryptPair[1]}
@@ -1,49 +1,86 @@
from UserDBLayer import COLLECTION_NAME as users
"""
This is basically an in-memory database that is used for the unit tests
and gets wiped when the tests are finished.
"""


from UserDBLayer import COLLECTION_NAME as TABLE_USER
from UserDBLayer import USER_LOGIN
from UserDBLayer import USER_PASSWORD
from UserDBLayer import USER_SALT
from Hero import COLLECTION_NAME as heros
from Account import COLLECTION_NAME as accounts
from Daily import COLLECTION_NAME as dailies
from Good import COLLECTION_NAME as goods
from Habit import COLLECTION_NAME as habits
from Monster import COLLECTION_NAME as monsters
from Todo import COLLECTION_NAME as todos
from Zone import COLLECTION_NAME as zones
import EverywhereConstants
from UserDBLayer import USER_DESC
from Hero import COLLECTION_NAME as TABLE_HEROS
from Account import COLLECTION_NAME as TABLE_ACCOUNTS
from Daily import COLLECTION_NAME as TABLE_DAILIES
from Good import COLLECTION_NAME as TABLE_GOODS
from Habit import COLLECTION_NAME as TABLE_HABITS
from Monster import COLLECTION_NAME as TABLE_MONSTERS
from Todo import COLLECTION_NAME as TABLE_TODOS
from Zone import COLLECTION_NAME as TABLE_ZONES
from Heap import Heap
import TestFunctionBuilder
import EverywhereConstants




testTables = {
users: {},
heros:{},
accounts:{},
dailies:{},
goods:{},
habits: {},
todos:{},
monsters:{},
zones:{}}



TABLE_USER: {},
TABLE_HEROS:{},
TABLE_ACCOUNTS:{},
TABLE_DAILIES:{},
TABLE_GOODS:{},
TABLE_HABITS: {},
TABLE_TODOS:{},
TABLE_MONSTERS:{},
TABLE_ZONES:{}}


#this is used to keep Ids unique
count = 0

def clean_up():
"""
set all of the dicts substituting for tables to empty dicts
and set count to 0 so that ids start from there and so
that it doesn't fuck with my unit tests that are dependant upon a
certain order
"""
global count
count = 0
for k,v in testTables.items():
v = {}

def get_table(tableName):
"""
gets the mock dataset associated with the given name.
args:
tableName:
name of the dataset that is wanted by the caller
returns:
a dict that itself contains a bunch of dicts
"""
if tableName not in testTables:
raise ConnectionError("This is not one of our tables")
return testTables[tableName]

def insert_thing(stuff, tableName):
"""
insert things into out mock database
args:
stuff:
this will be a dict. Ideally this will have most of the
same properties that the rest of the items in this dataset has.
tableName:
this is the name of the dataset that we're inserting
our item into.
returns:
the mock primary key of the newly inserted item. It will be of the
form: tableName + num, e.g. test0, hero7, etc.
"""
table = get_table(tableName)
global count
id = tableName + str(count)
@@ -53,6 +90,23 @@ def insert_thing(stuff, tableName):


def get_thing_by_id(id,tableName,returnReference = False):
"""
This is a wrapper method to get a single item from the mock database
that is associated with the given id.
args:
id:
this is a primary key for an item in the database
tableName:
this is the name of the dataset that is expected to have
the item we're looking for.
returnReference:
a boolean that determines if method returns a reference to the
dict or a copy of it.
returns:
a dict with an _id field that matches id
"""
table = get_table(tableName)
if id not in table:
return None
@@ -63,46 +117,85 @@ def get_thing_by_id(id,tableName,returnReference = False):


def update_thing_by_id(id,tableName,changes):
"""
This is a wrapper method for updating a single item in our mock db.
args:
id:
this is a primary key for an item in the database
tableName:
this is the name of the dataset that is expected to have
the item we're looking for.
changes:
this will be a dict. Each field in this dict will have a value
that overwrites the old value for that field for that item
in the db
"""
table = get_table(tableName)
testItem = get_thing_by_id(id,tableName,True)
for k,v in changes.items():
testItem[k] = v


def delete_thing_by_key(key,tableName):
"""
Removes a particular item from the mock database
args:
key:
primary key of the item that we want to remove from the db
tableName:
name of the dataSet that has the item that we want to remove
"""
table = get_table(tableName)
del table[key]

def get_user_collection():
return get_table(users)
return get_table(TABLE_USER)

def insert_user(login,pw,salt):
id = insert_thing({USER_LOGIN: login, USER_PASSWORD: pw, USER_SALT: salt},users)
def insert_user(login,pw):
id = insert_thing({USER_LOGIN: login.lower(), USER_PASSWORD: pw,USER_DESC:login},TABLE_USER)
return id

def does_login_exist(login):
users = get_user_collection()
for k,v in users.items():
if v[USER_LOGIN] == login:
lowerLogin = login.lower()
TABLE_USER = get_user_collection()
for k,v in TABLE_USER.items():
if v[USER_LOGIN] == lowerLogin:
return True
return False

def get_user(login):
users = get_user_collection()
for k,v in users.items():
if v[USER_LOGIN] == login:
lowerLogin = login.lower()
TABLE_USER = get_user_collection()
for k,v in TABLE_USER.items():
if v[USER_LOGIN] == lowerLogin:
return v
return None


def get_sorted_stuff_by_key(seachFor,tableName,sortByList):
def get_sorted_stuff_by_key(searchFor,tableName,sortByList):
table = get_table(tableName)
heap = Heap(TestFunctionBuilder.build_sort_by_function(sortByList,table))
for k,nestedDict in table.items():
isMatch = True
for e,a in seachFor.items():
for e,a in searchFor.items():
if not e in nestedDict or nestedDict[e] != a:
isMatch = False
break
if isMatch:
heap.push(nestedDict)
return heap.get_sorted_list()
return heap.get_sorted_list()

def get_count_of_stuff_search(searchFor,tableName):
table = get_table(tableName)
count = 0
for k,nestedDict in table.items():
isMatch = True
for e,a in searchFor.items():
if not e in nestedDict or nestedDict[e] != a:
isMatch = False
break
if isMatch:
count += 1
return count