Skip to content
This repository has been archived by the owner on Aug 22, 2022. It is now read-only.

JS Unit Tests & JSHint, using Jasmine #5

Merged
merged 12 commits into from
Sep 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 49 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,20 +1,48 @@
# Config
# OpenCraft -- tools to aid developing and hosting free software projects
# Copyright (C) 2015 OpenCraft <xavier@opencraft.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

# Config ######################################################################

WORKERS = 4
SHELL = /bin/bash


# Parameters ##################################################################

# For `test_one` use the rest as arguments and turn them into do-nothing targets
ifeq (test_one,$(firstword $(MAKECMDGOALS)))
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
$(eval $(RUN_ARGS):;@:)
endif


# Commands ####################################################################

all:
rundev

clean:
find -name '*.pyc' -delete
find -name '*~' -delete
find -name '__pycache__' -type d -delete
rm -rf .coverage build
find static/js/external -type f -not -name 'Makefile' -not -name '.gitignore' -delete

collectstatic: clean
collectstatic: clean js_external
honcho run ./manage.py collectstatic --noinput

migrate: clean
Expand All @@ -26,12 +54,18 @@ migration_check: clean
run: clean migration_check collectstatic
honcho start --concurrency "worker=$(WORKERS)"

rundev: clean migration_check
rundev: clean migration_check js_external
honcho start -f Procfile.dev

shell:
honcho run ./manage.py shell_plus

upgrade_dependencies:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U


# Tests #######################################################################

test_prospector: clean
prospector --profile opencraft

Expand All @@ -49,11 +83,20 @@ test_integration: clean
echo -e "\nIntegration tests skipped (create a '.env.integration' file to run them)" ; \
fi

test: clean test_prospector test_unit test_integration
test_js: clean js_external
cd instance/tests/js && jasmine-ci --logs --browser firefox

test_js_web: clean js_external
cd instance/tests/js && jasmine --host 0.0.0.0

test: clean test_prospector test_unit test_js test_integration
@echo -e "\nAll tests OK!\n"

test_one: clean
honcho -e .env.test run ./manage.py test $(RUN_ARGS)

upgrade_dependencies:
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U

# Files #######################################################################

js_external:
$(MAKE) -C static/js/external
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,18 @@ To run a single test, use `make test_one`:
$ make test_one instance.tests.models.test_server
```

You can also run prospector and the unit tests independently:
You can also run prospector, the unit tests, JS tests and integration independently:

```
$ make test_prospector
$ make test_unit
$ make test_js
$ make test_integration
```

JS tests can be run in your browser for debugging (see `make test_js_web` and then go to
http://localhost:8888/ ), or in a CI manner via selenium and `jasmine-ci` (see `make test_js`).

Note that the integration tests aren't run by default, as they require a working
OpenStack cluster configured. To run them, create a `.env.integration` file -
your development environment is likely a good starting point:
Expand Down
8 changes: 8 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,16 @@ Vagrant.configure(2) do |config|
config.vm.box = 'ubuntu/trusty64'
config.vm.network 'forwarded_port', guest: 2001, host: 2001
config.vm.network 'forwarded_port', guest: 5000, host: 5000
config.vm.network 'forwarded_port', guest: 8888, host: 8888
config.ssh.forward_x11 = true
config.vm.provision 'shell',
inline: PROVISION,
privileged: false,
keep_color: true

config.vm.provider :virtualbox do |vb|
# Allow DNS to work for Ubuntu host
# http://askubuntu.com/questions/238040/how-do-i-fix-name-service-for-vagrant-client
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
end
end
2 changes: 2 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ machine:
dependencies:
pre:
- pip install --upgrade pip
override:
- pip install -r requirements.txt
test:
override:
- make test:
Expand Down
1 change: 1 addition & 0 deletions debian_packages.lst
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ python3-pip
libpq-dev
python-dev
redis-server
firefox
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

(function(){
"use strict";


// App configuration //////////////////////////////////////////////////////////

var app = angular.module('InstanceApp', [
Expand Down Expand Up @@ -44,61 +44,42 @@ app.config(function($stateProvider, $urlRouterProvider, RestangularProvider) {
url: "/",
templateUrl: "/static/html/instance/index.html",
controller: "Index"
})
});
});


// Services ///////////////////////////////////////////////////////////////////

// Services
app.factory('OpenCraftAPI', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl('/api/v1');
});
});


// Function ///////////////////////////////////////////////////////////////////

function updateInstanceList($scope, OpenCraftAPI) {
// Display loading message
$scope.loading = true;

OpenCraftAPI.all("openedxinstance").getList().then(function(instanceList) {
console.log('Updating instance list', instanceList);
$scope.instanceList = instanceList;

if($scope.selected.instance){
var updated_instance = null;
_.each(instanceList, function(instance) {
if(instance.id === $scope.selected.instance.id) {
updated_instance = instance;
}
});
$scope.selected.instance = updated_instance;
}
}, function(response) {
console.log('Error from server: ', response);
}).finally(function () {
$scope.loading = false;
});
}


// Controllers ////////////////////////////////////////////////////////////////

app.controller("Index", ['$scope', 'Restangular', 'OpenCraftAPI', '$q',
function ($scope, Restangular, OpenCraftAPI, $q) {
// Display loading message
$scope.loading = true;

// Selection
$scope.selected = Array();
$scope.init = function() {
$scope.loading = true;
$scope.selected = {};

$scope.updateInstanceList();

// Init websockets
swampdragon.onChannelMessage($scope.handleChannelMessage);
swampdragon.ready(function() {
swampdragon.subscribe('notifier', 'notification', null);
swampdragon.subscribe('notifier', 'log', null);
});
};

$scope.select = function(selection_type, value) {
$scope.selected[selection_type] = value;
console.log('Selected ' + selection_type + ':', value);
};

// Reprovisioning
$scope.provision = function(instance) {
console.log('Provisioning instance', instance);
instance.status = 'terminating';
Expand All @@ -107,29 +88,48 @@ app.controller("Index", ['$scope', 'Restangular', 'OpenCraftAPI', '$q',
server.status = 'terminating';
}
});
instance.post("provision");
return instance.post("provision");
};

// Retrieve instance list
updateInstanceList($scope, OpenCraftAPI);
$scope.updateInstanceList = function() {
$scope.loading = true; // Display loading message

// Intialize websockets
swampdragon.onChannelMessage(function(channels, message) {
return OpenCraftAPI.all("openedxinstance").getList().then(function(instanceList) {
console.log('Updating instance list', instanceList);
$scope.instanceList = instanceList;

if($scope.selected.instance){
var updated_instance = null;
_.each(instanceList, function(instance) {
if(instance.id === $scope.selected.instance.id) {
updated_instance = instance;
}
});
$scope.selected.instance = updated_instance;
}
}, function(response) {
console.log('Error from server: ', response);
}).finally(function () {
$scope.loading = false;
});
};

$scope.handleChannelMessage = function(channels, message) {
console.log('Received websocket message', channels, message.data);

if(message.data.type === 'server_update') {
updateInstanceList($scope, OpenCraftAPI);
$scope.updateInstanceList();
} else if(message.data.type === 'instance_log') {
if($scope.selected.instance && $scope.selected.instance.id === message.data.instance_id) {
$scope.$apply(function(){
$scope.selected.instance.log_text += message.data.log_entry + '\n';
});
}
}
});
swampdragon.ready(function() {
swampdragon.subscribe('notifier', 'notification', null);
swampdragon.subscribe('notifier', 'log', null);
});
};

$scope.init();
}
]);

})();
2 changes: 1 addition & 1 deletion instance/templates/instance/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
{% block body_js %}
{% swampdragon_settings %}
<script src="{% static 'swampdragon/js/dist/swampdragon.min.js' %}"></script>
<script src="{% static "js/instance.js" %}"></script>
<script src="{% static "js/src/instance.js" %}"></script>
{% endblock body_js %}
61 changes: 61 additions & 0 deletions instance/tests/fixtures/api/instances_list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[
{
"id": 2,
"api_url": "http://localhost:5000/api/v1/openedxinstance/2/",
"active_server_set": [
{
"id": 23,
"api_url": "http://localhost:5000/api/v1/openstackserver/23/",
"created": "2015-08-20T06:40:18.835733Z",
"instance": "http://localhost:5000/api/v1/openedxinstance/2/",
"modified": "2015-08-20T12:12:34.781802Z",
"openstack_id": "f889c46a-975a-4ecb-acb8-b6c3c5f97c8e",
"status": "ready"
}
],
"base_domain": "opencraft.com",
"branch_name": "master",
"commit_id": "24bca27b46a0e65c00628716a77d19a6c5aecd55",
"created": "2015-08-08T07:22:56.062796Z",
"domain": "tmp.sandbox.opencraft.com",
"email": "contact@example.com",
"github_base_url": "https://github.com/antoviaque/edx-platform",
"github_branch_url": "https://github.com/antoviaque/edx-platform/tree/master",
"log_text": "2015-08-08 07:23:16 [info] Terminate servers for instance tmp.sandbox - antoviaque/edx-platform/master (24bca27) (http://tmp.sandbox.opencraft.com/)...\n2015-08-08 07:23:16 [info] Start new server for instance tmp.sandbox - antoviaque/edx-platform/master (24bca27) (http://tmp.sandbox.opencraft.com/)...\n2015-08-08 07:23:18 [info] Waiting for IP assignment on server 3841c324-c004-4188-9d8c-f1071cd635c5...\n"
},
{
"id": 1,
"api_url": "http://localhost:5000/api/v1/openedxinstance/1/",
"active_server_set": [
{
"id": 19,
"api_url": "http://localhost:5000/api/v1/openstackserver/19/",
"created": "2015-08-18T05:48:55.163364Z",
"instance": "http://localhost:5000/api/v1/openedxinstance/1/",
"modified": "2015-08-18T05:48:56.360140Z",
"openstack_id": "c007b320-1643-4f95-838a-1467ab0927e7",
"status": "started"
}
],
"base_domain": "opencraft.com",
"branch_name": "OC-791-course-timeline",
"commit_id": "40952060bc7573c5035620b985b211a24360f311",
"created": "2015-08-07T18:10:56.823929Z",
"domain": "pr2.sandbox.opencraft.com",
"email": "contact@example.com",
"github_base_url": "https://github.com/antoviaque/edx-platform",
"github_branch_url": "https://github.com/antoviaque/edx-platform/tree/OC-791-course-timeline",
"log_text": "2015-08-07 18:10:56 [info] Terminate servers for instance PR#2: Display start date, end date, and number of sections (weeks) on \"Course Info\" tab of instructor dashboard. (antoviaque) - antoviaque/edx-platform/OC-791-course-timeline (4095206) (http://pr2.sandbox.opencraft.com/)...\n",
"github_organization_name": "antoviaque",
"modified": "2015-08-18T05:48:54.356884Z",
"name": "PR#2: Display start date, end date, and number of sections (weeks) on \"Course Info\" tab of instructor dashboard. (antoviaque) - antoviaque/edx-platform/OC-791-course-timeline (4095206)",
"protocol": "http",
"repository_url": "https://github.com/antoviaque/edx-platform.git",
"status": "started",
"studio_url": "http://studio.pr2.sandbox.opencraft.com/",
"sub_domain": "pr2.sandbox",
"url": "http://pr2.sandbox.opencraft.com/",
"updates_feed": "https://github.com/antoviaque/edx-platform/commits/OC-791-course-timeline.atom",
"vars_str": "# System\nCOMMON_HOSTNAME: 'pr2.sandbox.opencraft.com'\n\n# edxapp\nEDXAPP_PLATFORM_NAME: \"PR#2: Display start date, end date, and number of sections (weeks) on &quot;Course Info&quot; tab of instructor dashboard. (antoviaque) - antoviaque/edx-platform/OC-791-course-timeline (4095206)\"\nEDXAPP_LMS_NGINX_PORT: 80\nEDXAPP_LMS_PREVIEW_NGINX_PORT: 80\nEDXAPP_CMS_NGINX_PORT: 80\nEDXAPP_SITE_NAME: 'pr2.sandbox.opencraft.com'\nEDXAPP_LMS_SITE_NAME: 'pr2.sandbox.opencraft.com'\nEDXAPP_LMS_BASE: 'pr2.sandbox.opencraft.com'\nEDXAPP_PREVIEW_LMS_BASE: 'pr2.sandbox.opencraft.com'\n\nEDXAPP_CMS_SITE_NAME: 'studio.pr2.sandbox.opencraft.com'\nEDXAPP_CMS_BASE: 'studio.pr2.sandbox.opencraft.com'\n\n# Forum environment settings\nFORUM_RACK_ENV: 'production'\nFORUM_SINATRA_ENV: 'production'\n\n# Emails\nEDXAPP_CONTACT_EMAIL: 'contact@example.com'\nEDXAPP_TECH_SUPPORT_EMAIL: 'contact@example.com'\nEDXAPP_BUGS_EMAIL: 'contact@example.com'\nEDXAPP_FEEDBACK_SUBMISSION_EMAIL: 'contact@example.com'\nEDXAPP_DEFAULT_FROM_EMAIL: 'contact@example.com'\nEDXAPP_DEFAULT_FEEDBACK_EMAIL: 'contact@example.com'\nEDXAPP_SERVER_EMAIL: 'contact@example.com'\nEDXAPP_BULK_EMAIL_DEFAULT_FROM_EMAIL: 'contact@example.com'\n\n# Misc\nEDXAPP_TIME_ZONE: 'UTC'\n\n# Security updates\nCOMMON_SECURITY_UPDATES: true\nSECURITY_UNATTENDED_UPGRADES: true\nSECURITY_UPDATE_ALL_PACKAGES: false\nSECURITY_UPGRADE_ON_ANSIBLE: true\n\n# Repositories URLs\nedx_ansible_source_repo: 'https://github.com/edx/configuration.git'\nedx_platform_repo: 'https://github.com/antoviaque/edx-platform.git'\n\n# Pin down dependencies to specific (known to be compatible) commits.\nedx_platform_version: '40952060bc7573c5035620b985b211a24360f311'\nconfiguration_version: 'master'\nforum_version: 'master'\nnotifier_version: 'master'\nxqueue_version: 'master'\ncerts_version: 'master'\n\n# Features\nEDXAPP_FEATURES:\n USE_MICROSITES: false\n AUTH_USE_OPENID: false\n ENABLE_DISCUSSION_SERVICE: true\n ENABLE_INSTRUCTOR_ANALYTICS: true\n ENABLE_INSTRUCTOR_EMAIL: true\n REQUIRE_COURSE_EMAIL_AUTH: false\n ENABLE_PEARSON_HACK_TEST: false\n SUBDOMAIN_BRANDING: false\n SUBDOMAIN_COURSE_LISTINGS: false\n PREVIEW_LMS_BASE: 'pr2.sandbox.opencraft.com'\n ENABLE_DJANGO_ADMIN_SITE: true\n ALLOW_ALL_ADVANCED_COMPONENTS: true\n\n\n"
}
]
28 changes: 28 additions & 0 deletions instance/tests/js/helpers/fixtures.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// OpenCraft -- tools to aid developing and hosting free software projects
// Copyright (C) 2015 OpenCraft <xavier@opencraft.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

(function(){
"use strict";

// Functions //////////////////////////////////////////////////////////////////

// Load the JS object from a JSON fixture
jasmine.loadFixture = function(fixturePath) {
var fixtureJSON = jasmine.httpGET('/__src__/instance/tests/fixtures/' + fixturePath);
return JSON.parse(fixtureJSON);
};

})();
Loading