Commit 2302c324 by Vik Paruchuri

Merge branch 'feature/vik/disable-spell-check' into feature/vik/check-if-submission-allowed

parents 72d06982 c48998b3
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
[run] [run]
data_file = reports/cms/.coverage data_file = reports/cms/.coverage
source = cms,common/djangoapps source = cms,common/djangoapps
omit = cms/envs/*, cms/manage.py, common/djangoapps/*/migrations/* omit = cms/envs/*, cms/manage.py, common/djangoapps/terrain/*, common/djangoapps/*/migrations/*
[report] [report]
ignore_errors = True ignore_errors = True
......
...@@ -146,6 +146,7 @@ def add_section(name='My Section'): ...@@ -146,6 +146,7 @@ def add_section(name='My Section'):
span_css = 'span.section-name-span' span_css = 'span.section-name-span'
assert_true(world.browser.is_element_present_by_css(span_css, 5)) assert_true(world.browser.is_element_present_by_css(span_css, 5))
def add_subsection(name='Subsection One'): def add_subsection(name='Subsection One'):
css = 'a.new-subsection-item' css = 'a.new-subsection-item'
css_click(css) css_click(css)
......
...@@ -59,4 +59,4 @@ def i_am_on_tab(step, tab_name): ...@@ -59,4 +59,4 @@ def i_am_on_tab(step, tab_name):
@step('I see a link for adding a new section$') @step('I see a link for adding a new section$')
def i_see_new_section_link(step): def i_see_new_section_link(step):
link_css = 'a.new-courseware-section-button' link_css = 'a.new-courseware-section-button'
assert_css_with_text(link_css, 'New Section') assert_css_with_text(link_css, '+ New Section')
...@@ -342,7 +342,7 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -342,7 +342,7 @@ class ContentStoreTest(ModuleStoreTestCase):
# Create a course so there is something to view # Create a course so there is something to view
resp = self.client.get(reverse('index')) resp = self.client.get(reverse('index'))
self.assertContains(resp, self.assertContains(resp,
'<h1>My Courses</h1>', '<h1 class="title-1">My Courses</h1>',
status_code=200, status_code=200,
html=True) html=True)
......
...@@ -131,7 +131,8 @@ def index(request): ...@@ -131,7 +131,8 @@ def index(request):
reverse('course_index', args=[ reverse('course_index', args=[
course.location.org, course.location.org,
course.location.course, course.location.course,
course.location.name])) course.location.name]),
get_lms_link_for_item(course.location))
for course in courses], for course in courses],
'user': request.user, 'user': request.user,
'disable_course_creation': settings.MITX_FEATURES.get('DISABLE_COURSE_CREATION', False) and not request.user.is_staff 'disable_course_creation': settings.MITX_FEATURES.get('DISABLE_COURSE_CREATION', False) and not request.user.is_staff
...@@ -172,6 +173,8 @@ def course_index(request, org, course, name): ...@@ -172,6 +173,8 @@ def course_index(request, org, course, name):
if not has_access(request.user, location): if not has_access(request.user, location):
raise PermissionDenied() raise PermissionDenied()
lms_link = get_lms_link_for_item(location)
upload_asset_callback_url = reverse('upload_asset', kwargs={ upload_asset_callback_url = reverse('upload_asset', kwargs={
'org': org, 'org': org,
'course': course, 'course': course,
...@@ -184,6 +187,7 @@ def course_index(request, org, course, name): ...@@ -184,6 +187,7 @@ def course_index(request, org, course, name):
return render_to_response('overview.html', { return render_to_response('overview.html', {
'active_tab': 'courseware', 'active_tab': 'courseware',
'context_course': course, 'context_course': course,
'lms_link': lms_link,
'sections': sections, 'sections': sections,
'course_graders': json.dumps(CourseGradingModel.fetch(course.location).graders), 'course_graders': json.dumps(CourseGradingModel.fetch(course.location).graders),
'parent_location': course.location, 'parent_location': course.location,
......
class CMS.Views.TabsEdit extends Backbone.View class CMS.Views.TabsEdit extends Backbone.View
events:
'click .new-tab': 'addNewTab'
initialize: => initialize: =>
@$('.component').each((idx, element) => @$('.component').each((idx, element) =>
...@@ -13,6 +11,7 @@ class CMS.Views.TabsEdit extends Backbone.View ...@@ -13,6 +11,7 @@ class CMS.Views.TabsEdit extends Backbone.View
) )
) )
@options.mast.find('.new-tab').on('click', @addNewTab)
@$('.components').sortable( @$('.components').sortable(
handle: '.drag-handle' handle: '.drag-handle'
update: @tabMoved update: @tabMoved
......
...@@ -43,6 +43,12 @@ $(document).ready(function () { ...@@ -43,6 +43,12 @@ $(document).ready(function () {
$('body').addClass('js'); $('body').addClass('js');
// lean/simple modal
$('a[rel*=modal]').leanModal({overlay : 0.80, closeButton: '.action-modal-close' });
$('a.action-modal-close').click(function(e){
(e).preventDefault();
});
// nav - dropdown related // nav - dropdown related
$body.click(function (e) { $body.click(function (e) {
$('.nav-dropdown .nav-item .wrapper-nav-sub').removeClass('is-shown'); $('.nav-dropdown .nav-item .wrapper-nav-sub').removeClass('is-shown');
...@@ -638,7 +644,7 @@ function addNewCourse(e) { ...@@ -638,7 +644,7 @@ function addNewCourse(e) {
$(e.target).hide(); $(e.target).hide();
var $newCourse = $($('#new-course-template').html()); var $newCourse = $($('#new-course-template').html());
var $cancelButton = $newCourse.find('.new-course-cancel'); var $cancelButton = $newCourse.find('.new-course-cancel');
$('.new-course-button').after($newCourse); $('.inner-wrapper').prepend($newCourse);
$newCourse.find('.new-course-name').focus().select(); $newCourse.find('.new-course-name').focus().select();
$newCourse.find('form').bind('submit', saveNewCourse); $newCourse.find('form').bind('submit', saveNewCourse);
$cancelButton.bind('click', cancelNewCourse); $cancelButton.bind('click', cancelNewCourse);
...@@ -822,4 +828,4 @@ function saveSetSectionScheduleDate(e) { ...@@ -822,4 +828,4 @@ function saveSetSectionScheduleDate(e) {
hideModal(); hideModal();
}); });
} }
\ No newline at end of file
...@@ -10,7 +10,7 @@ CMS.Views.CourseInfoEdit = Backbone.View.extend({ ...@@ -10,7 +10,7 @@ CMS.Views.CourseInfoEdit = Backbone.View.extend({
render: function() { render: function() {
// instantiate the ClassInfoUpdateView and delegate the proper dom to it // instantiate the ClassInfoUpdateView and delegate the proper dom to it
new CMS.Views.ClassInfoUpdateView({ new CMS.Views.ClassInfoUpdateView({
el: this.$('#course-update-view'), el: $('body.updates'),
collection: this.model.get('updates') collection: this.model.get('updates')
}); });
...@@ -27,10 +27,10 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({ ...@@ -27,10 +27,10 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
// collection is CourseUpdateCollection // collection is CourseUpdateCollection
events: { events: {
"click .new-update-button" : "onNew", "click .new-update-button" : "onNew",
"click .save-button" : "onSave", "click #course-update-view .save-button" : "onSave",
"click .cancel-button" : "onCancel", "click #course-update-view .cancel-button" : "onCancel",
"click .edit-button" : "onEdit", "click .post-actions > .edit-button" : "onEdit",
"click .delete-button" : "onDelete" "click .post-actions > .delete-button" : "onDelete"
}, },
initialize: function() { initialize: function() {
......
...@@ -50,7 +50,142 @@ h1 { ...@@ -50,7 +50,142 @@ h1 {
// ==================== // ====================
// layout - basic // layout - basic page header
.wrapper-mast {
margin: 0;
padding: 0 $baseline;
position: relative;
.mast, .metadata {
@include clearfix();
@include font-size(16);
position: relative;
max-width: $fg-max-width;
min-width: $fg-min-width;
width: flex-grid(12);
margin: 0 auto $baseline auto;
color: $gray-d2;
}
.mast {
border-bottom: 1px solid $gray-l4;
padding-bottom: ($baseline/2);
.title-sub {
@include font-size(14);
position: relative;
top: ($baseline/4);
display: block;
margin: 0;
color: $gray-l2;
font-weight: 400;
}
.title, .title-1 {
@include font-size(32);
margin: 0;
padding: 0;
font-weight: 600;
color: $gray-d3;
}
.nav-hierarchy {
@include font-size(14);
display: block;
margin: 0;
color: $gray-l2;
font-weight: 400;
.nav-item {
display: inline;
vertical-align: middle;
margin-right: ($baseline/4);
&:after {
content: ">>";
margin-left: ($baseline/4);
}
&:last-child {
margin-right: 0;
&:after {
content: none;
}
}
}
}
// layout with actions
.title {
width: flex-grid(12);
}
// layout with actions
&.has-actions {
@include clearfix();
.title {
float: left;
width: flex-grid(6,12);
margin-right: flex-gutter();
}
.nav-actions {
position: relative;
bottom: -($baseline*0.75);
float: right;
width: flex-grid(6,12);
text-align: right;
.nav-item {
display: inline-block;
vertical-align: top;
margin-right: ($baseline/2);
&:last-child {
margin-right: 0;
}
}
// buttons
.button {
padding: ($baseline/4) ($baseline/2) ($baseline/3) ($baseline/2) !important;
font-weight: 400 !important;
}
.new-button {
font-weight: 700 !important;
}
.view-button {
font-weight: 700 !important;
}
.upload-button .icon-create {
@include font-size(18);
margin-top: ($baseline/4);
}
}
}
// layout with actions
&.has-subtitle {
.nav-actions {
bottom: -($baseline*1.5);
}
}
}
// page metadata/action bar
.metadata {
}
}
// layout - basic page content
.wrapper-content { .wrapper-content {
margin: 0; margin: 0;
padding: 0 $baseline; padding: 0 $baseline;
...@@ -89,8 +224,39 @@ h1 { ...@@ -89,8 +224,39 @@ h1 {
} }
.introduction { .introduction {
@include box-sizing(border-box);
@include font-size(14); @include font-size(14);
width: flex-grid(12);
margin: 0 0 $baseline 0; margin: 0 0 $baseline 0;
.copy strong {
font-weight: 600;
}
&.has-links {
@include clearfix();
.copy {
float: left;
width: flex-grid(8,12);
margin-right: flex-gutter();
}
.nav-introduction-supplementary {
@include font-size(13);
float: right;
width: flex-grid(4,12);
display: block;
text-align: right;
.icon {
@include font-size(14);
display: inline-block;
vertical-align: middle;
margin-right: ($baseline/4);
}
}
}
} }
} }
...@@ -98,6 +264,7 @@ h1 { ...@@ -98,6 +264,7 @@ h1 {
@include box-sizing(border-box); @include box-sizing(border-box);
} }
// layout - primary content
.content-primary { .content-primary {
.title-1, .title-2, .title-3, .title-4, .title-5, .title-5 { .title-1, .title-2, .title-3, .title-4, .title-5, .title-5 {
...@@ -129,6 +296,7 @@ h1 { ...@@ -129,6 +296,7 @@ h1 {
} }
} }
// layout - supplemental content
.content-supplementary { .content-supplementary {
.bit { .bit {
...@@ -494,22 +662,49 @@ hr.divide { ...@@ -494,22 +662,49 @@ hr.divide {
.new-button { .new-button {
@include green-button; @include green-button;
font-size: 13px; @include font-size(13);
padding: 8px 20px 10px; padding: 8px 20px 10px;
text-align: center; text-align: center;
&.big { &.big {
display: block; display: block;
} }
.icon-create {
display: inline-block;
vertical-align: middle;
margin-right: ($baseline/4);
margin-top: ($baseline/10);
line-height: 0;
}
}
.view-button {
@include blue-button;
@include font-size(13);
text-align: center;
&.big {
display: block;
}
.icon-view {
@include font-size(15);
display: inline-block;
vertical-align: middle;
margin-right: ($baseline/2);
margin-top: ($baseline/5);
line-height: 0;
}
} }
.edit-button.standard, .edit-button.standard,
.delete-button.standard { .delete-button.standard {
float: left; @include font-size(12);
@include white-button; @include white-button;
float: left;
padding: 3px 10px 4px; padding: 3px 10px 4px;
margin-left: 7px; margin-left: 7px;
font-size: 12px;
font-weight: 400; font-weight: 400;
.edit-icon, .edit-icon,
...@@ -579,6 +774,72 @@ hr.divide { ...@@ -579,6 +774,72 @@ hr.divide {
// ==================== // ====================
// js dependant
body.js {
// lean/simple modal window
.content-modal {
@include border-bottom-radius(2px);
@include box-sizing(border-box);
@include box-shadow(0 2px 4px $shadow-d1);
position: relative;
display: none;
width: 700px;
overflow: hidden;
border: 1px solid $gray-d1;
padding: ($baseline);
background: $white;
.action-modal-close {
@include transition(top .25s ease-in-out);
@include border-bottom-radius(3px);
position: absolute;
top: -3px;
right: $baseline;
padding: ($baseline/4) ($baseline/2) 0 ($baseline/2);
background: $gray-l3;
text-align: center;
.label {
@include text-sr();
}
.ss-icon {
@include font-size(18);
color: $white;
}
&:hover {
background: $blue;
top: 0;
}
}
img {
@include box-sizing(border-box);
width: 100%;
overflow-y: scroll;
padding: ($baseline/10);
border: 1px solid $gray-l4;
}
.title {
@include font-size(18);
margin: 0 0 ($baseline/2) 0;
font-weight: 600;
color: $gray-d3;
}
.description {
@include font-size(13);
margin-top: ($baseline/2);
color: $gray-l1;
}
}
}
// ====================
// works in progress // works in progress
body.hide-wip { body.hide-wip {
......
...@@ -37,6 +37,11 @@ ...@@ -37,6 +37,11 @@
padding: 34px 0 42px; padding: 34px 0 42px;
border-top: 1px solid #cbd1db; border-top: 1px solid #cbd1db;
&:first-child {
padding-top: 0;
border: none;
}
&.editing { &.editing {
position: relative; position: relative;
z-index: 1001; z-index: 1001;
......
...@@ -6,19 +6,27 @@ ...@@ -6,19 +6,27 @@
@include box-shadow(0 1px 2px rgba(0, 0, 0, .1)); @include box-shadow(0 1px 2px rgba(0, 0, 0, .1));
li { li {
position: relative;
border-bottom: 1px solid $mediumGrey; border-bottom: 1px solid $mediumGrey;
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
} }
}
a { .class-link {
padding: 20px 25px; z-index: 100;
line-height: 1.3; display: block;
padding: 20px 25px;
&:hover { line-height: 1.3;
background: $paleYellow;
&:hover {
background: $paleYellow;
+ .view-live-button {
opacity: 1.0;
pointer-events: auto;
}
}
} }
} }
...@@ -34,6 +42,22 @@ ...@@ -34,6 +42,22 @@
margin-right: 20px; margin-right: 20px;
color: #3c3c3c; color: #3c3c3c;
} }
// view live button
.view-live-button {
z-index: 10000;
position: absolute;
top: 15px;
right: $baseline;
padding: ($baseline/4) ($baseline/2);
opacity: 0;
pointer-events: none;
&:hover {
opacity: 1.0;
pointer-events: auto;
}
}
} }
.new-course { .new-course {
......
...@@ -350,67 +350,4 @@ ...@@ -350,67 +350,4 @@
} }
} }
} }
}
// js dependant \ No newline at end of file
&.js {
.content-modal {
@include border-bottom-radius(2px);
@include box-sizing(border-box);
@include box-shadow(0 2px 4px $shadow-d1);
position: relative;
display: none;
width: 700px;
overflow: hidden;
border: 1px solid $gray-d1;
padding: ($baseline);
background: $white;
.action-modal-close {
@include transition(top .25s ease-in-out);
@include border-bottom-radius(3px);
position: absolute;
top: -3px;
right: $baseline;
padding: ($baseline/4) ($baseline/2) 0 ($baseline/2);
background: $gray-l3;
text-align: center;
.label {
@include text-sr();
}
.ss-icon {
@include font-size(18);
color: $white;
}
&:hover {
background: $blue;
top: 0;
}
}
img {
@include box-sizing(border-box);
width: 100%;
overflow-y: scroll;
padding: ($baseline/10);
border: 1px solid $gray-l4;
}
.title {
@include font-size(18);
margin: 0 0 ($baseline/2) 0;
font-weight: 600;
color: $gray-d3;
}
.description {
@include font-size(13);
margin-top: ($baseline/2);
color: $gray-l1;
}
}
}
}
...@@ -28,8 +28,9 @@ ...@@ -28,8 +28,9 @@
border-radius: 0; border-radius: 0;
&.new-component-item { &.new-component-item {
margin-top: 20px;
background: transparent; background: transparent;
border: none;
@include box-shadow(none);
} }
} }
......
...@@ -33,12 +33,27 @@ ...@@ -33,12 +33,27 @@
</tr> </tr>
</script> </script>
<div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle">
<div class="title">
<span class="title-sub">Course Content</span>
<h1 class="title-1">Files &amp; Uploads</h1>
</div>
<nav class="nav-actions">
<h3 class="sr">Page Actions</h3>
<ul>
<li class="nav-item">
<a href="#" class="button upload-button new-button"><i class="ss-icon ss-symbolicons-standard icon icon-create">&#xEB40;</i> Upload New File</a>
</li>
</ul>
</nav>
</header>
</div>
<div class="main-wrapper"> <div class="main-wrapper">
<div class="inner-wrapper"> <div class="inner-wrapper">
<div class="page-actions"> <div class="page-actions">
<a href="#" class="upload-button new-button">
<span class="upload-icon"></span>Upload New Asset
</a>
<input type="text" class="asset-search-input search wip-box" placeholder="search assets" style="display:none"/> <input type="text" class="asset-search-input search wip-box" placeholder="search assets" style="display:none"/>
</div> </div>
<article class="asset-library"> <article class="asset-library">
......
...@@ -42,16 +42,38 @@ ...@@ -42,16 +42,38 @@
</%block> </%block>
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle">
<div class="title">
<span class="title-sub">Course Content</span>
<h1 class="title-1">Course Updates</h1>
</div>
<nav class="nav-actions">
<h3 class="sr">Page Actions</h3>
<ul>
<li class="nav-item">
<a href="#" class=" button new-button new-update-button"><i class="ss-icon ss-symbolicons-standard icon icon-create">&#x002B;</i> New Update</a>
</li>
</ul>
</nav>
</header>
</div>
<div class="wrapper-content wrapper">
<section class="content">
<div class="introduction">
<p clas="copy">Course updates are announcements or notifications you want to share with your class. Other course authors have used them for important exam/date reminders, change in schedules, and to call out any important steps students need to be aware of.</p>
</div>
</section>
</div>
<div class="main-wrapper"> <div class="main-wrapper">
<div class="inner-wrapper"> <div class="inner-wrapper">
<h1>Course Info</h1>
<div class="course-info-wrapper"> <div class="course-info-wrapper">
<div class="main-column window"> <div class="main-column window">
<article class="course-updates" id="course-update-view"> <article class="course-updates" id="course-update-view">
<h2>Course Updates & News</h2>
<a href="#" class="new-update-button">New Update</a>
<ol class="update-list" id="course-update-list"></ol> <ol class="update-list" id="course-update-list"></ol>
<!-- probably replace w/ a vertical where each element of the vertical is a separate update w/ a date and html field -->
</article> </article>
</div> </div>
<div class="sidebar window course-handouts" id="course-handouts-view"></div> <div class="sidebar window course-handouts" id="course-handouts-view"></div>
......
...@@ -9,25 +9,49 @@ ...@@ -9,25 +9,49 @@
el: $('.main-wrapper'), el: $('.main-wrapper'),
model: new CMS.Models.Module({ model: new CMS.Models.Module({
id: '${context_course.location}' id: '${context_course.location}'
}) }),
mast: $('.wrapper-mast')
}); });
</script> </script>
</%block> </%block>
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle">
<div class="title">
<span class="title-sub">Course Content</span>
<h1 class="title-1">Static Pages</h1>
</div>
<nav class="nav-actions">
<h3 class="sr">Page Actions</h3>
<ul>
<li class="nav-item">
<a href="#" class="button new-button new-tab"><i class="ss-icon ss-symbolicons-standard icon icon-create">&#x002B;</i> New Page</a>
</li>
</ul>
</nav>
</header>
</div>
<div class="wrapper-content wrapper">
<section class="content">
<div class="introduction has-links">
<p class="copy">Static Pages are additional pages that supplement your Courseware. Other course authors have used them to share a syllabus, calendar, handouts, and more.</p>
<nav class="nav-introduction-supplementary">
<ul>
<li class="nav-item">
<a rel="modal" href="#preview-lms-staticpages"><i class="ss-icon ss-symbolicons-block icon icon-information">&#x2753;</i>How do Static Pages look to students in my course?</a>
</li>
</ul>
</nav>
</div>
</section>
</div>
<div class="main-wrapper"> <div class="main-wrapper">
<div class="inner-wrapper"> <div class="inner-wrapper">
<article class="unit-body"> <article class="unit-body">
<div class="details">
<h2>Here you can add and manage additional pages for your course</h2>
<p>These pages will be added to the primary navigation menu alongside Courseware, Course Info, Discussion, etc.</p>
</div>
<div class="page-actions">
<a href="#" class="new-button new-tab">
<span class="plus-icon white"></span>New Page
</a>
</div>
<div class="tab-list"> <div class="tab-list">
<ol class='components'> <ol class='components'>
...@@ -43,4 +67,17 @@ ...@@ -43,4 +67,17 @@
</article> </article>
</div> </div>
</div> </div>
<div class="content-modal" id="preview-lms-staticpages">
<h3 class="title">How Static Pages are Used in Your Course</h3>
<figure>
<img src="/static/img/preview-lms-staticpages.png" alt="Preview of how Static Pages are used in your course" />
<figcaption class="description">These pages will be presented in your course's main navigation alongside Courseware, Course Info, Discussion, etc.</figcaption>
</figure>
<a href="#" rel="view" class="action action-modal-close">
<i class="ss-icon ss-symbolicons-block icon-close icon">&#x2421;</i>
<span class="label">close modal</span>
</a>
</div>
</%block> </%block>
\ No newline at end of file
...@@ -6,6 +6,15 @@ ...@@ -6,6 +6,15 @@
<%block name="bodyclass">is-signedin course tools export</%block> <%block name="bodyclass">is-signedin course tools export</%block>
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper">
<header class="mast has-subtitle">
<div class="title">
<span class="title-sub">Tools</span>
<h1 class="title-1">Course Export</h1>
</div>
</header>
</div>
<div class="main-wrapper"> <div class="main-wrapper">
<div class="inner-wrapper"> <div class="inner-wrapper">
<article class="export-overview"> <article class="export-overview">
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<img src="/static/img/thumb-hiw-feature1.png" alt="Studio Helps You Keep Your Courses Organized" /> <img src="/static/img/thumb-hiw-feature1.png" alt="Studio Helps You Keep Your Courses Organized" />
<figcaption class="sr">Studio Helps You Keep Your Courses Organized</figcaption> <figcaption class="sr">Studio Helps You Keep Your Courses Organized</figcaption>
<span class="action-zoom"> <span class="action-zoom">
<i class="ss-icon ss-symbolicons-block">&#xE002;</i> <i class="ss-icon ss-symbolicons-block icon icon-zoom">&#xE002;</i>
</span> </span>
</a> </a>
</figure> </figure>
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
<img src="/static/img/thumb-hiw-feature2.png" alt="Learning is More than Just Lectures" /> <img src="/static/img/thumb-hiw-feature2.png" alt="Learning is More than Just Lectures" />
<figcaption class="sr">Learning is More than Just Lectures</figcaption> <figcaption class="sr">Learning is More than Just Lectures</figcaption>
<span class="action-zoom"> <span class="action-zoom">
<i class="ss-icon ss-symbolicons-block">&#xE002;</i> <i class="ss-icon ss-symbolicons-block icon icon-zoom">&#xE002;</i>
</span> </span>
</a> </a>
</figure> </figure>
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
<img src="/static/img/thumb-hiw-feature3.png" alt="Studio Gives You Simple, Fast, and Incremental Publishing. With Friends." /> <img src="/static/img/thumb-hiw-feature3.png" alt="Studio Gives You Simple, Fast, and Incremental Publishing. With Friends." />
<figcaption class="sr">Studio Gives You Simple, Fast, and Incremental Publishing. With Friends.</figcaption> <figcaption class="sr">Studio Gives You Simple, Fast, and Incremental Publishing. With Friends.</figcaption>
<span class="action-zoom"> <span class="action-zoom">
<i class="ss-icon ss-symbolicons-block">&#xE002;</i> <i class="ss-icon ss-symbolicons-block icon icon-zoom">&#xE002;</i>
</span> </span>
</a> </a>
</figure> </figure>
...@@ -152,7 +152,7 @@ ...@@ -152,7 +152,7 @@
</figure> </figure>
<a href="#" rel="view" class="action action-modal-close"> <a href="#" rel="view" class="action action-modal-close">
<i class="ss-icon ss-symbolicons-block">&#x2421;</i> <i class="ss-icon ss-symbolicons-block icon icon-close">&#x2421;</i>
<span class="label">close modal</span> <span class="label">close modal</span>
</a> </a>
</div> </div>
...@@ -165,7 +165,7 @@ ...@@ -165,7 +165,7 @@
</figure> </figure>
<a href="#" rel="view" class="action action-modal-close"> <a href="#" rel="view" class="action action-modal-close">
<i class="ss-icon ss-symbolicons-block">&#x2421;</i> <i class="ss-icon ss-symbolicons-block icon icon-close">&#x2421;</i>
<span class="label">close modal</span> <span class="label">close modal</span>
</a> </a>
</div> </div>
...@@ -178,22 +178,8 @@ ...@@ -178,22 +178,8 @@
</figure> </figure>
<a href="#" rel="view" class="action action-modal-close"> <a href="#" rel="view" class="action action-modal-close">
<i class="ss-icon ss-symbolicons-block">&#x2421;</i> <i class="ss-icon ss-symbolicons-block icon icon-close">&#x2421;</i>
<span class="label">close modal</span> <span class="label">close modal</span>
</a> </a>
</div> </div>
</%block>
<%block name="jsextra">
<script type="text/javascript">
(function() {
// lean modal window
$('a[rel*=modal]').leanModal({overlay : 0.50, closeButton: '.action-modal-close' });
$('a.action-modal-close').click(function(e){
(e).preventDefault();
});
})(this)
</script>
</%block> </%block>
\ No newline at end of file
...@@ -6,6 +6,15 @@ ...@@ -6,6 +6,15 @@
<%block name="bodyclass">is-signedin course tools import</%block> <%block name="bodyclass">is-signedin course tools import</%block>
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper">
<header class="mast has-subtitle">
<div class="title">
<span class="title-sub">Tools</span>
<h1 class="title-1">Course Import</h1>
</div>
</header>
</div>
<div class="main-wrapper"> <div class="main-wrapper">
<div class="inner-wrapper"> <div class="inner-wrapper">
<article class="import-overview"> <article class="import-overview">
......
...@@ -33,35 +33,57 @@ ...@@ -33,35 +33,57 @@
</%block> </%block>
<%block name="content"> <%block name="content">
<div class="main-wrapper"> <div class="wrapper-mast wrapper">
<div class="inner-wrapper"> <header class="mast has-actions">
<h1>My Courses</h1> <div class="title">
<article class="my-classes"> <h1 class="title-1">My Courses</h1>
% if user.is_active: </div>
% if not disable_course_creation:
<a href="#" class="new-button new-course-button"><span class="plus-icon white"></span> New Course</a> % if user.is_active:
%endif <nav class="nav-actions">
<ul class="class-list"> <h3 class="sr">Page Actions</h3>
%for course, url in courses: <ul>
<li> <li class="nav-item">
<a href="${url}" class="class-name"> % if not disable_course_creation:
<span class="class-name">${course}</span> <a href="#" class="button new-button new-course-button"><i class="ss-icon ss-symbolicons-standard icon icon-create">&#x002B;</i> New Course</a>
<!-- % endif
<span class="detail">Started: 9/21/2012</span> </li>
<span class="detail">Ends: 10/21/2012</span> </ul>
--> </nav>
</a> % endif
</li> </header>
%endfor </div>
</ul>
% else: <div class="wrapper-content wrapper">
<div class='warn-msg'> <section class="content">
<p> <div class="introduction">
In order to start authoring courses using edX studio, please click on the activation link in your email. <p class="copy"><strong>Welcome, ${ user.username }</strong>. Here are all of the courses you are currently authoring in Studio:</p>
</p> </div>
</div> </section>
% endif </div>
</article>
</div> <div class="main-wrapper">
</div> <div class="inner-wrapper">
</%block> <article class="my-classes">
% if user.is_active:
<ul class="class-list">
%for course, url, lms_link in courses:
<li>
<a class="class-link" href="${url}" class="class-name">
<span class="class-name">${course}</span>
</a>
<a href="${lms_link}" rel="external" class="button view-button view-live-button"><i class="ss-icon ss-symbolicons-block icon icon-view">&#xE010;</i>View Live</a>
</li>
%endfor
</ul>
% else:
<div class='warn-msg'>
<p>
In order to start authoring courses using edX Studio, please click on the activation link in your email.
</p>
</div>
% endif
</article>
</div>
</div>
</%block>
\ No newline at end of file
...@@ -4,15 +4,28 @@ ...@@ -4,15 +4,28 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle">
<div class="title">
<span class="title-sub">Course Settings</span>
<h1 class="title-1">Course Team</h1>
</div>
<nav class="nav-actions">
<h3 class="sr">Page Actions</h3>
<ul>
%if allow_actions:
<li class="nav-item">
<a href="#" class="button new-button new-user-button"><i class="ss-icon ss-symbolicons-standard icon icon-create">&#x002B;</i> New User</a>
</li>
%endif
</ul>
</nav>
</header>
</div>
<div class="main-wrapper"> <div class="main-wrapper">
<div class="inner-wrapper"> <div class="inner-wrapper">
<div class="page-actions">
%if allow_actions:
<a href="#" class="new-button new-user-button">
<span class="plus-icon white"></span>New User
</a>
%endif
</div>
<div class="details"> <div class="details">
<p>The following list of users have been designated as course staff. This means that these users will have permissions to modify course content. You may add additional course staff below, if you are the course instructor. Please note that they must have already registered and verified their account.</p> <p>The following list of users have been designated as course staff. This means that these users will have permissions to modify course content. You may add additional course staff below, if you are the course instructor. Please note that they must have already registered and verified their account.</p>
......
...@@ -120,12 +120,32 @@ ...@@ -120,12 +120,32 @@
</div> </div>
</div> </div>
<div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle">
<div class="title">
<span class="title-sub">Course Content</span>
<h1 class="title-1">Course Outline</h1>
</div>
<nav class="nav-actions">
<h3 class="sr">Page Actions</h3>
<ul>
<li class="nav-item">
<a href="#" class="toggle-button toggle-button-sections"><i class="ss-icon ss-symbolicons-block icon">up</i> <span class="label">Collapse All Sections</span></a>
</li>
<li class="nav-item">
<a href="#" class="button new-button new-courseware-section-button"><i class="ss-icon ss-symbolicons-standard icon icon-create">&#x002B;</i> New Section</a>
</li>
<li class="nav-item">
<a href="${lms_link}" rel="external" class="button view-button view-live-button"><i class="ss-icon ss-symbolicons-block icon icon-view">&#xE010;</i>View Live</a>
</li>
</ul>
</nav>
</header>
</div>
<div class="main-wrapper"> <div class="main-wrapper">
<div class="inner-wrapper"> <div class="inner-wrapper">
<div class="page-actions">
<a href="#" class="new-button new-courseware-section-button"><span class="plus-icon white"></span> New Section</a>
<a href="#" class="toggle-button toggle-button-sections"><i class="ss-icon ss-symbolicons-block">up</i> <span class="label">Collapse All Sections</span></a>
</div>
<article class="courseware-overview" data-course-id="${context_course.location.url()}"> <article class="courseware-overview" data-course-id="${context_course.location.url()}">
% for section in sections: % for section in sections:
<section class="courseware-section branch" data-id="${section.location}"> <section class="courseware-section branch" data-id="${section.location}">
......
...@@ -42,17 +42,17 @@ from contentstore import utils ...@@ -42,17 +42,17 @@ from contentstore import utils
</%block> </%block>
<%block name="content"> <%block name="content">
<div class="wrapper-content wrapper"> <div class="wrapper-mast wrapper">
<section class="content"> <header class="mast has-subtitle">
<header class="page"> <div class="title">
<span class="title-sub">Settings</span> <span class="title-sub">Settings</span>
<h1 class="title-1">Schedule &amp; Details</h1> <h1 class="title-1">Schedule &amp; Details</h1>
</header> </div>
</header>
<!-- <div class="introduction"> </div>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.</p>
</div> -->
<div class="wrapper-content wrapper">
<section class="content">
<article class="content-primary" role="main"> <article class="content-primary" role="main">
<form id="settings_details" class="settings-details" method="post" action=""> <form id="settings_details" class="settings-details" method="post" action="">
<section class="group-settings basic"> <section class="group-settings basic">
......
...@@ -39,17 +39,17 @@ from contentstore import utils ...@@ -39,17 +39,17 @@ from contentstore import utils
</%block> </%block>
<%block name="content"> <%block name="content">
<div class="wrapper-content wrapper"> <div class="wrapper-mast wrapper">
<section class="content"> <header class="mast has-subtitle">
<header class="page"> <div class="title">
<span class="title-sub">Settings</span> <span class="title-sub">Settings</span>
<h1 class="title-1">Grading</h1> <h1 class="title-1">Grading</h1>
</header> </div>
</header>
<!-- <div class="introduction"> </div>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.</p>
</div> -->
<div class="wrapper-content wrapper">
<section class="content">
<article class="content-primary" role="main"> <article class="content-primary" role="main">
<form id="settings_details" class="settings-grading" method="post" action=""> <form id="settings_details" class="settings-grading" method="post" action="">
<section class="group-settings grade-range"> <section class="group-settings grade-range">
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
</div> </div>
<nav class="nav-course primary nav-dropdown" role="navigation"> <nav class="nav-course primary nav-dropdown" role="navigation">
<h2 class="sr">PH207x's Navigation:</h2> <h2 class="sr">${context_course.display_name}'s Navigation:</h2>
<ol> <ol>
<li class="nav-item nav-course-courseware"> <li class="nav-item nav-course-courseware">
......
...@@ -12,6 +12,8 @@ import capa.xqueue_interface as xqueue_interface ...@@ -12,6 +12,8 @@ import capa.xqueue_interface as xqueue_interface
from datetime import datetime from datetime import datetime
from . import test_system from . import test_system
import test_util_open_ended
""" """
Tests for the various pieces of the CombinedOpenEndedGrading system Tests for the various pieces of the CombinedOpenEndedGrading system
...@@ -43,7 +45,10 @@ class OpenEndedChildTest(unittest.TestCase): ...@@ -43,7 +45,10 @@ class OpenEndedChildTest(unittest.TestCase):
'max_score': max_score, 'max_score': max_score,
'display_name': 'Name', 'display_name': 'Name',
'accept_file_upload': False, 'accept_file_upload': False,
'close_date': None 'close_date': None,
's3_interface' : "",
'open_ended_grading_interface' : {},
'skip_basic_checks' : False,
} }
definition = Mock() definition = Mock()
descriptor = Mock() descriptor = Mock()
...@@ -161,6 +166,9 @@ class OpenEndedModuleTest(unittest.TestCase): ...@@ -161,6 +166,9 @@ class OpenEndedModuleTest(unittest.TestCase):
'accept_file_upload': False, 'accept_file_upload': False,
'rewrite_content_links' : "", 'rewrite_content_links' : "",
'close_date': None, 'close_date': None,
's3_interface' : test_util_open_ended.S3_INTERFACE,
'open_ended_grading_interface' : test_util_open_ended.OPEN_ENDED_GRADING_INTERFACE,
'skip_basic_checks' : False,
} }
oeparam = etree.XML(''' oeparam = etree.XML('''
...@@ -293,6 +301,9 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): ...@@ -293,6 +301,9 @@ class CombinedOpenEndedModuleTest(unittest.TestCase):
'accept_file_upload' : False, 'accept_file_upload' : False,
'rewrite_content_links' : "", 'rewrite_content_links' : "",
'close_date' : "", 'close_date' : "",
's3_interface' : test_util_open_ended.S3_INTERFACE,
'open_ended_grading_interface' : test_util_open_ended.OPEN_ENDED_GRADING_INTERFACE,
'skip_basic_checks' : False,
} }
oeparam = etree.XML(''' oeparam = etree.XML('''
......
...@@ -9,6 +9,7 @@ from nose.plugins.skip import SkipTest ...@@ -9,6 +9,7 @@ from nose.plugins.skip import SkipTest
from . import test_system from . import test_system
import test_util_open_ended
class SelfAssessmentTest(unittest.TestCase): class SelfAssessmentTest(unittest.TestCase):
...@@ -47,7 +48,10 @@ class SelfAssessmentTest(unittest.TestCase): ...@@ -47,7 +48,10 @@ class SelfAssessmentTest(unittest.TestCase):
'max_score': 1, 'max_score': 1,
'display_name': "Name", 'display_name': "Name",
'accept_file_upload': False, 'accept_file_upload': False,
'close_date': None 'close_date': None,
's3_interface' : test_util_open_ended.S3_INTERFACE,
'open_ended_grading_interface' : test_util_open_ended.OPEN_ENDED_GRADING_INTERFACE,
'skip_basic_checks' : False,
} }
self.module = SelfAssessmentModule(test_system, self.location, self.module = SelfAssessmentModule(test_system, self.location,
......
OPEN_ENDED_GRADING_INTERFACE = {
'url' : 'http://127.0.0.1:3033/',
'username' : 'incorrect',
'password' : 'incorrect',
'staff_grading' : 'staff_grading',
'peer_grading' : 'peer_grading',
'grading_controller' : 'grading_controller'
}
S3_INTERFACE = {
'aws_access_key' : "",
'aws_secret_key' : "",
"aws_bucket_name" : "",
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
[run] [run]
data_file = reports/lms/.coverage data_file = reports/lms/.coverage
source = lms,common/djangoapps source = lms,common/djangoapps
omit = lms/envs/*, lms/djangoapps/portal/*, lms/djangoapps/terrain/*, common/djangoapps/*/migrations/* omit = lms/envs/*, common/djangoapps/terrain/*, common/djangoapps/*/migrations/*
[report] [report]
ignore_errors = True ignore_errors = True
......
from lettuce import world, step # , before, after from lettuce import world, step
from factories import *
from django.core.management import call_command from django.core.management import call_command
from nose.tools import assert_equals, assert_in from nose.tools import assert_equals, assert_in
from lettuce.django import django_url from lettuce.django import django_url
......
...@@ -9,7 +9,6 @@ logger = getLogger(__name__) ...@@ -9,7 +9,6 @@ logger = getLogger(__name__)
## support functions ## support functions
def get_courses(): def get_courses():
''' '''
Returns dict of lists of courses available, keyed by course.org (ie university). Returns dict of lists of courses available, keyed by course.org (ie university).
...@@ -20,29 +19,6 @@ def get_courses(): ...@@ -20,29 +19,6 @@ def get_courses():
courses = sorted(courses, key=lambda course: course.number) courses = sorted(courses, key=lambda course: course.number)
return courses return courses
# def get_courseware(course_id):
# """
# Given a course_id (string), return a courseware array of dictionaries for the
# top two levels of navigation. Example:
# [
# {'chapter_name': 'Overview',
# 'sections': ['Welcome', 'System Usage Sequence', 'Lab0: Using the tools', 'Circuit Sandbox']
# },
# {'chapter_name': 'Week 1',
# 'sections': ['Administrivia and Circuit Elements', 'Basic Circuit Analysis', 'Resistor Divider', 'Week 1 Tutorials']
# },
# {'chapter_name': 'Midterm Exam',
# 'sections': ['Midterm Exam']
# }
# ]
# """
# course = get_course_by_id(course_id)
# chapters = course.get_children()
# courseware = [ {'chapter_name':c.display_name, 'sections':[s.display_name for s in c.get_children()]} for c in chapters]
# return courseware
def get_courseware_with_tabs(course_id): def get_courseware_with_tabs(course_id):
""" """
...@@ -106,8 +82,8 @@ def get_courseware_with_tabs(course_id): ...@@ -106,8 +82,8 @@ def get_courseware_with_tabs(course_id):
course = get_course_by_id(course_id) course = get_course_by_id(course_id)
chapters = [chapter for chapter in course.get_children() if chapter.metadata.get('hide_from_toc', 'false').lower() != 'true'] chapters = [chapter for chapter in course.get_children() if chapter.metadata.get('hide_from_toc', 'false').lower() != 'true']
courseware = [{'chapter_name': c.display_name, courseware = [{'chapter_name': c.display_name,
'sections': [{'section_name': s.display_name, 'sections': [{'section_name': s.display_name,
'clickable_tab_count': len(s.get_children()) if (type(s) == seq_module.SequenceDescriptor) else 0, 'clickable_tab_count': len(s.get_children()) if (type(s) == seq_module.SequenceDescriptor) else 0,
'tabs': [{'children_count': len(t.get_children()) if (type(t) == vertical_module.VerticalDescriptor) else 0, 'tabs': [{'children_count': len(t.get_children()) if (type(t) == vertical_module.VerticalDescriptor) else 0,
'class': t.__class__.__name__} 'class': t.__class__.__name__}
for t in s.get_children()]} for t in s.get_children()]}
......
...@@ -9,10 +9,3 @@ Feature: View the Courseware Tab ...@@ -9,10 +9,3 @@ Feature: View the Courseware Tab
And I click on View Courseware And I click on View Courseware
When I click on the "Courseware" tab When I click on the "Courseware" tab
Then the "Courseware" tab is active Then the "Courseware" tab is active
# TODO: fix this one? Not sure whether you should get a 404.
# Scenario: I cannot get to the courseware tab when not logged in
# Given I am not logged in
# And I visit the homepage
# When I visit the courseware URL
# Then the login dialog is visible
...@@ -34,7 +34,6 @@ def click_the_dropdown(step): ...@@ -34,7 +34,6 @@ def click_the_dropdown(step):
#### helper functions #### helper functions
def user_is_an_unactivated_user(uname): def user_is_an_unactivated_user(uname):
u = User.objects.get(username=uname) u = User.objects.get(username=uname)
u.is_active = False u.is_active = False
......
...@@ -3,31 +3,35 @@ Feature: Open ended grading ...@@ -3,31 +3,35 @@ Feature: Open ended grading
In order to complete the courseware questions In order to complete the courseware questions
I want the machine learning grading to be functional I want the machine learning grading to be functional
Scenario: An answer that is too short is rejected # Commenting these all out right now until we can
Given I navigate to an openended question # make a reference implementation for a course with
And I enter the answer "z" # an open ended grading problem that is always available
When I press the "Check" button #
And I wait for "8" seconds # Scenario: An answer that is too short is rejected
And I see the grader status "Submitted for grading" # Given I navigate to an openended question
And I press the "Recheck for Feedback" button # And I enter the answer "z"
Then I see the red X # When I press the "Check" button
And I see the grader score "0" # And I wait for "8" seconds
# And I see the grader status "Submitted for grading"
# And I press the "Recheck for Feedback" button
# Then I see the red X
# And I see the grader score "0"
Scenario: An answer with too many spelling errors is rejected # Scenario: An answer with too many spelling errors is rejected
Given I navigate to an openended question # Given I navigate to an openended question
And I enter the answer "az" # And I enter the answer "az"
When I press the "Check" button # When I press the "Check" button
And I wait for "8" seconds # And I wait for "8" seconds
And I see the grader status "Submitted for grading" # And I see the grader status "Submitted for grading"
And I press the "Recheck for Feedback" button # And I press the "Recheck for Feedback" button
Then I see the red X # Then I see the red X
And I see the grader score "0" # And I see the grader score "0"
When I click the link for full output # When I click the link for full output
Then I see the spelling grading message "More spelling errors than average." # Then I see the spelling grading message "More spelling errors than average."
Scenario: An answer makes its way to the instructor dashboard # Scenario: An answer makes its way to the instructor dashboard
Given I navigate to an openended question as staff # Given I navigate to an openended question as staff
When I submit the answer "I love Chemistry." # When I submit the answer "I love Chemistry."
And I wait for "8" seconds # And I wait for "8" seconds
And I visit the staff grading page # And I visit the staff grading page
Then my answer is queued for instructor grading # Then my answer is queued for instructor grading
\ No newline at end of file
...@@ -14,4 +14,4 @@ Feature: Register for a course ...@@ -14,4 +14,4 @@ Feature: Register for a course
And I visit the dashboard And I visit the dashboard
When I click the link with the text "Unregister" When I click the link with the text "Unregister"
And I press the "Unregister" button in the Unenroll dialog And I press the "Unregister" button in the Unenroll dialog
Then I should see "Looks like you haven't registered for any courses yet." somewhere in the page Then I should see "Looks like you haven't registered for any courses yet." somewhere in the page
\ No newline at end of file
...@@ -4,7 +4,7 @@ from lettuce import world, step ...@@ -4,7 +4,7 @@ from lettuce import world, step
@step('I register for the course numbered "([^"]*)"$') @step('I register for the course numbered "([^"]*)"$')
def i_register_for_the_course(step, course): def i_register_for_the_course(step, course):
courses_section = world.browser.find_by_css('section.courses') courses_section = world.browser.find_by_css('section.courses')
course_link_css = 'article[id*="%s"] a' % course course_link_css = 'article[id*="%s"] > div' % course
course_link = courses_section.find_by_css(course_link_css).first course_link = courses_section.find_by_css(course_link_css).first
course_link.click() course_link.click()
...@@ -25,3 +25,4 @@ def i_should_see_that_course_in_my_dashboard(step, course): ...@@ -25,3 +25,4 @@ def i_should_see_that_course_in_my_dashboard(step, course):
def i_press_the_button_in_the_unenroll_dialog(step, value): def i_press_the_button_in_the_unenroll_dialog(step, value):
button_css = 'section#unenroll-modal input[value="%s"]' % value button_css = 'section#unenroll-modal input[value="%s"]' % value
world.browser.find_by_css(button_css).click() world.browser.find_by_css(button_css).click()
assert world.browser.is_element_present_by_css('section.container.dashboard')
...@@ -23,37 +23,41 @@ Feature: There are courses on the homepage ...@@ -23,37 +23,41 @@ Feature: There are courses on the homepage
As an acceptance test As an acceptance test
I want to count all the chapters, sections, and tabs for each course I want to count all the chapters, sections, and tabs for each course
Scenario: Navigate through course MITx/3.091x/2012_Fall # Commenting these all out for now because they don't always run,
Given I am registered for course "MITx/3.091x/2012_Fall" # they have too many prerequesites, e.g. the course exists, and
And I log in # is within the start and end dates, etc.
Then I verify all the content of each course
# Scenario: Navigate through course MITx/3.091x/2012_Fall
Scenario: Navigate through course MITx/6.002x/2012_Fall # Given I am registered for course "MITx/3.091x/2012_Fall"
Given I am registered for course "MITx/6.002x/2012_Fall" # And I log in
And I log in # Then I verify all the content of each course
Then I verify all the content of each course
# Scenario: Navigate through course MITx/6.002x/2012_Fall
Scenario: Navigate through course MITx/6.00x/2012_Fall # Given I am registered for course "MITx/6.002x/2012_Fall"
Given I am registered for course "MITx/6.00x/2012_Fall" # And I log in
And I log in # Then I verify all the content of each course
Then I verify all the content of each course
# Scenario: Navigate through course MITx/6.00x/2012_Fall
Scenario: Navigate through course HarvardX/PH207x/2012_Fall # Given I am registered for course "MITx/6.00x/2012_Fall"
Given I am registered for course "HarvardX/PH207x/2012_Fall" # And I log in
And I log in # Then I verify all the content of each course
Then I verify all the content of each course
# Scenario: Navigate through course HarvardX/PH207x/2012_Fall
Scenario: Navigate through course BerkeleyX/CS169.1x/2012_Fall # Given I am registered for course "HarvardX/PH207x/2012_Fall"
Given I am registered for course "BerkeleyX/CS169.1x/2012_Fall" # And I log in
And I log in # Then I verify all the content of each course
Then I verify all the content of each course
# Scenario: Navigate through course BerkeleyX/CS169.1x/2012_Fall
Scenario: Navigate through course BerkeleyX/CS169.2x/2012_Fall # Given I am registered for course "BerkeleyX/CS169.1x/2012_Fall"
Given I am registered for course "BerkeleyX/CS169.2x/2012_Fall" # And I log in
And I log in # Then I verify all the content of each course
Then I verify all the content of each course
# Scenario: Navigate through course BerkeleyX/CS169.2x/2012_Fall
Scenario: Navigate through course BerkeleyX/CS184.1x/2012_Fall # Given I am registered for course "BerkeleyX/CS169.2x/2012_Fall"
Given I am registered for course "BerkeleyX/CS184.1x/2012_Fall" # And I log in
And I log in # Then I verify all the content of each course
Then I verify all the content of each course
\ No newline at end of file # Scenario: Navigate through course BerkeleyX/CS184.1x/2012_Fall
# Given I am registered for course "BerkeleyX/CS184.1x/2012_Fall"
# And I log in
# Then I verify all the content of each course
\ No newline at end of file
...@@ -26,6 +26,8 @@ log = logging.getLogger(__name__) ...@@ -26,6 +26,8 @@ log = logging.getLogger(__name__)
from django.test.utils import override_settings from django.test.utils import override_settings
from django.http import QueryDict from django.http import QueryDict
from xmodule.tests import test_util_open_ended
@override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE) @override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE)
class TestStaffGradingService(ct.PageLoader): class TestStaffGradingService(ct.PageLoader):
...@@ -145,9 +147,11 @@ class TestPeerGradingService(ct.PageLoader): ...@@ -145,9 +147,11 @@ class TestPeerGradingService(ct.PageLoader):
location = "i4x://edX/toy/peergrading/init" location = "i4x://edX/toy/peergrading/init"
self.mock_service = peer_grading_service.MockPeerGradingService() self.mock_service = peer_grading_service.MockPeerGradingService()
self.system = ModuleSystem(location, None, None, render_to_string, None) self.system = ModuleSystem(location, None, None, render_to_string, None,
s3_interface = test_util_open_ended.S3_INTERFACE,
open_ended_grading_interface=test_util_open_ended.OPEN_ENDED_GRADING_INTERFACE
)
self.descriptor = peer_grading_module.PeerGradingDescriptor(self.system) self.descriptor = peer_grading_module.PeerGradingDescriptor(self.system)
self.peer_module = peer_grading_module.PeerGradingModule(self.system, location, "<peergrading/>", self.descriptor) self.peer_module = peer_grading_module.PeerGradingModule(self.system, location, "<peergrading/>", self.descriptor)
self.peer_module.peer_gs = self.mock_service self.peer_module.peer_gs = self.mock_service
self.logout() self.logout()
......
## acceptance_testing
This fake django app is here to support acceptance testing using <a href="http://lettuce.it/">lettuce</a> +
<a href="http://splinter.cobrateam.info/">splinter</a> (which wraps <a href="http://selenium.googlecode.com/svn/trunk/docs/api/py/index.html">selenium</a>).
First you need to make sure that you've installed the requirements.
This includes lettuce, selenium, splinter, etc.
Do this with:
```pip install -r test-requirements.txt```
The settings.py environment file used is named acceptance.py.
It uses a test SQLite database defined as ../db/test-mitx.db.
You need to first start up the server separately, then run the lettuce scenarios.
Full documentation can be found on the wiki at <a href="https://edx-wiki.atlassian.net/wiki/display/ENG/Lettuce+Acceptance+Testing">this link</a>.
import factory
from student.models import User, UserProfile, Registration
from datetime import datetime
import uuid
class UserProfileFactory(factory.Factory):
FACTORY_FOR = UserProfile
user = None
name = 'Jack Foo'
level_of_education = None
gender = 'm'
mailing_address = None
goals = 'World domination'
class RegistrationFactory(factory.Factory):
FACTORY_FOR = Registration
user = None
activation_key = uuid.uuid4().hex
class UserFactory(factory.Factory):
FACTORY_FOR = User
username = 'robot'
email = 'robot+test@edx.org'
password = 'test'
first_name = 'Robot'
last_name = 'Test'
is_staff = False
is_active = True
is_superuser = False
last_login = datetime(2012, 1, 1)
date_joined = datetime(2011, 1, 1)
...@@ -38,4 +38,4 @@ MITX_FEATURES['STUB_VIDEO_FOR_TESTING'] = True ...@@ -38,4 +38,4 @@ MITX_FEATURES['STUB_VIDEO_FOR_TESTING'] = True
# Include the lettuce app for acceptance testing, including the 'harvest' django-admin command # Include the lettuce app for acceptance testing, including the 'harvest' django-admin command
INSTALLED_APPS += ('lettuce.django',) INSTALLED_APPS += ('lettuce.django',)
LETTUCE_APPS = ('portal',) # dummy app covers the home page, login, registration, and course enrollment LETTUCE_APPS = ('courseware',)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment