diff --git a/cypress/integration/exports/student_competencies.js b/cypress/integration/exports/student_competencies.js new file mode 100644 index 000000000..5f5ab8d8a --- /dev/null +++ b/cypress/integration/exports/student_competencies.js @@ -0,0 +1,65 @@ +const csvtojson = require('csvtojson'); + +describe('Student Competencies Export', () => { + it('Download and Verify Student Competencies Export via Form', () => { + cy.loginAs('admin'); + cy.visit('/exports') + cy.contains('h2', 'Competency Progress') + + // prepare for form submission that returns back a file + // https://on.cypress.io/intercept + cy.intercept({ + pathname: '/exports/slate-cbl/student-competencies', + }, (req) => { + // instead of redirecting to the CSV file + // and having the browser deal with it + // download the file ourselves + // but we cannot use Cypress commands inside the callback + // thus we will download it later using the captured URL + req.redirect('/exports') + }).as('records') + + cy.get('form[action="/exports/slate-cbl/student-competencies"]').within(() => { + cy.get('input[name=students]').type('{selectall}{backspace}student'); + cy.get('select[name=content_area]').select('English Language Arts'); + cy.get('select[name=level]').select('highest'); + + cy.root().submit(); + }) + + cy.wait('@records').its('request').then((req) => { + cy.request(req) + .then(({ body, headers }) => { + expect(headers).to.have.property('content-type', 'text/csv; charset=utf-8') + return csvtojson().fromString(body) + }).then((records) => { + expect(records, 'One row per competency skill').to.have.length(7); + expect( + records[0]['Performance Level'], + 'ELA.1 for student has Performance Level 9.3 ((8+9+10+10)/4 = 9.25 rounded to 9.3)' + ).to.equal('9.3'); + expect( + records[0]['Progress'], + 'ELA.1 for student has 33% Progress (4/12 Demonstrations Required for Competency)' + ).to.equal('0.33'); + expect( + records[0]['Growth'], + 'ELA.1 for student has -1.5 growth' + ).to.equal('-1.5') + + expect( + records[1]['Performance Level'], + 'ELA.2 for student has Performance Level 9.3 ((11+11+11+10)/4 = 10.75 rounded to 10.8)' + ).to.equal('10.8') + expect( + records[1]['Progress'], + 'ELA.2 for student has 33% Progress (4/15 Demonstrations Required for Competency)' + ).to.equal('0.27') + expect( + records[1]['Growth'], + 'ELA.2 for student has 1 growth' + ).to.equal('1') + }) + }) + }) +}) \ No newline at end of file diff --git a/data-exporters/slate-cbl/student-competencies.php b/data-exporters/slate-cbl/student-competencies.php index 1435e897e..8d9da7531 100644 --- a/data-exporters/slate-cbl/student-competencies.php +++ b/data-exporters/slate-cbl/student-competencies.php @@ -130,16 +130,6 @@ while ($record = $result->fetch_assoc()) { $StudentCompetency = Slate\CBL\StudentCompetency::instantiateRecord($record); - $demonstrationsComplete = $StudentCompetency->getDemonstrationsComplete(); - $demonstrationsRequired = $StudentCompetency->getDemonstrationsRequired(); - $demonstrationsAverage = round( - $StudentCompetency->getDemonstrationsAverage(), - Slate\CBL\StudentCompetency::$averagePrecision - ); - $growth = round( - $StudentCompetency->getGrowth(), - Slate\CBL\StudentCompetency::$averagePrecision - ); yield [ 'ID' => $StudentCompetency->ID, @@ -149,12 +139,12 @@ 'StudentFullName' => $Student->FullName, 'CompetencyCode' => $StudentCompetency->Competency->Code, 'Level' => $StudentCompetency->Level, - 'BaselineRating' => round($StudentCompetency->BaselineRating, 1), - 'DemonstrationsAverage' => $demonstrationsAverage ?: null, - 'Growth' => $growth ?: null, - 'Progress' => round($demonstrationsRequired ? $demonstrationsComplete/$demonstrationsRequired : 1, 2), - 'DemonstrationsRequired' => $demonstrationsRequired, - 'DemonstrationsComplete' => $demonstrationsComplete, + 'BaselineRating' => $StudentCompetency->getBaselineRating(), + 'DemonstrationsAverage' => $StudentCompetency->getDemonstrationsAverage() ?: null, + 'Growth' => $StudentCompetency->getGrowth() ?: null, + 'Progress' => $StudentCompetency->getProgress() ?: null, + 'DemonstrationsRequired' => $StudentCompetency->getDemonstrationsRequired(), + 'DemonstrationsComplete' => $StudentCompetency->getDemonstrationsComplete(), 'DemonstrationsMissed' => $StudentCompetency->getDemonstrationsMissed(), 'DemonstrationOpportunities' => $StudentCompetency->getDemonstrationOpportunities() ]; diff --git a/php-classes/Slate/CBL/StudentCompetency.php b/php-classes/Slate/CBL/StudentCompetency.php index 55cfae680..1e46ca6e0 100644 --- a/php-classes/Slate/CBL/StudentCompetency.php +++ b/php-classes/Slate/CBL/StudentCompetency.php @@ -23,6 +23,7 @@ class StudentCompetency extends \ActiveRecord public static $isLevelComplete; public static $growthCalculatorClass = Calculators\Growth\MostRecentMinusFirst::class; public static $averagePrecision = 1; + public static $progressPrecision = 2; // ActiveRecord configuration @@ -117,6 +118,9 @@ class StudentCompetency extends \ActiveRecord 'growth' => [ 'getter' => 'getGrowth' ], + 'progress' => [ + 'getter' => 'getProgress' + ], 'next' => [ 'getter' => 'getNext' ] @@ -524,7 +528,19 @@ public function getGrowth() $this->competencyGrowth = $growthCalculationClass::calculateGrowth($this); } - return $this->competencyGrowth === false ? null : $this->competencyGrowth; + return $this->competencyGrowth === false ? null : round($this->competencyGrowth, static::$averagePrecision); + } + + private $competencyProgress; + public function getProgress() + { + if ($this->competencyProgress === null) { + $required = $this->getDemonstrationsRequired(); + $complete = $this->getDemonstrationsComplete(); + $this->competencyProgress = $required ? $complete / $required : 1; + } + + return $this->competencyProgress === false ? null : round($this->competencyProgress, static::$progressPrecision); } private $previous;