Add frontend assets and plugin bundles

Add the legacy frontend themes, scripts, and plugin assets required by the main SPOTA interfaces.
This commit is contained in:
Power BI Dev
2026-05-02 10:09:32 +07:00
parent efdb11db3f
commit a52c2a8462
2061 changed files with 513282 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
feature("Backspace Key", function() {
story('User presses backspace with cursor to the right of a mask literal',function(){
scenario('character at cursor matches definition to the left',function(){
given("an input with a mask definition of '9-99'", function(){
input
.mask("9-99")
.mashKeys("123");
});
given("the input has cursor positioned to the right of literal", function(){
input.caret(2);
});
when("hitting the backspace key",function(){
input.mashKeys(function(keys){keys.type(keys.backspace)});
});
then("value should be correct",function(){
expect(input).toHaveValue('2-3_');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
scenario('character at cursor does not match definition to the left',function(){
given("an input with a mask definition of 'a-99'", function(){
input
.mask("a-99")
.mashKeys("z12");
});
given("the input has cursor positioned to the right of literal", function(){
input.caret(2);
});
when("hitting the backspace key",function(){
input.mashKeys(function(keys){keys.type(keys.backspace)});
});
then("value should be correct",function(){
expect(input).toHaveValue('_-12');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
});
story('User presses backspace with cursor on last character',function(){
scenario('cursor character matches definition to the left',function(){
given("an input with a mask definition of '99'", function(){
input
.mask("99")
.mashKeys("12");
});
given("the input has cursor positioned on first character", function(){
input.caret(1);
});
when("hitting the backspace key",function(){
input.mashKeys(function(keys){keys.type(keys.backspace)});
});
then("value should be correct",function(){
expect(input).toHaveValue('2_');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
scenario('cursor character does not match definition to the left',function(){
given("an input with a mask definition of '9a'", function(){
input
.mask("9a")
.mashKeys("1z");
});
given("the input has cursor positioned on first character", function(){
input.caret(1);
});
when("hitting the backspace key",function(){
input.mashKeys(function(keys){keys.type(keys.backspace)});
});
then("value should be correct",function(){
expect(input).toHaveValue('_z');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
describe('There is a mask literal between the two placeholders',function(){
scenario('character at end matches definition of first position',function(){
given("an input with a mask definition of '9-9'", function(){
input
.mask("9-9")
.mashKeys("12");
});
given("the input has cursor positioned on literal", function(){
input.caret(1);
});
when("hitting the backspace key",function(){
input.mashKeys(function(keys){keys.type(keys.backspace)});
});
then("value should be correct",function(){
expect(input).toHaveValue('2-_');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
scenario('character at end does not match definition of first position',function(){
given("an input with a mask definition of '9-9'", function(){
input
.mask("9-a")
.mashKeys("1z");
});
given("the input has cursor positioned on literal", function(){
input.caret(1);
});
when("hitting the backspace key",function(){
input.mashKeys(function(keys){keys.type(keys.backspace)});
});
then("value should be correct",function(){
expect(input).toHaveValue('_-z');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
});
});
});

View File

@@ -0,0 +1,151 @@
feature("Delete Key", function() {
story('User presses delete with cursor on a mask literal',function(){
scenario('character at end matches definition to the right',function(){
given("an input with a mask definition of '9-99'", function(){
input
.mask("9-99")
.mashKeys("123");
});
given("the input has cursor positioned on literal", function(){
input.caret(1);
});
when("hitting the delete key",function(){
input.mashKeys(function(keys){keys.type(keys.delete)});
});
then("value should be correct",function(){
expect(input).toHaveValue('1-3_');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(2);
});
});
scenario('character at end does not match definition to the right',function(){
given("an input with a mask definition of '9-9a'", function(){
input
.mask("9-9a")
.mashKeys("12z");
});
given("the input has cursor positioned on literal", function(){
input.caret(1);
});
when("hitting the delete key",function(){
input.mashKeys(function(keys){keys.type(keys.delete)});
});
then("value should be correct",function(){
expect(input).toHaveValue('1-_z');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(2);
});
});
});
story('User presses delete with cursor on first character',function(){
scenario('character to right matches definition of current position',function(){
given("an input with a mask definition of '99'", function(){
input
.mask("99")
.mashKeys("12");
});
given("the input has cursor positioned on first character", function(){
input.caret(0);
});
when("hitting the delete key",function(){
input.mashKeys(function(keys){keys.type(keys.delete)});
});
then("value should be correct",function(){
expect(input).toHaveValue('2_');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
scenario('character to right does not match definition of current position',function(){
given("an input with a mask definition of '9a'", function(){
input
.mask("9a")
.mashKeys("1z");
});
given("the input has cursor positioned on first character", function(){
input.caret(0);
});
when("hitting the delete key",function(){
input.mashKeys(function(keys){keys.type(keys.delete)});
});
then("value should be correct",function(){
expect(input).toHaveValue('_z');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
describe('There is a mask literal between the two placeholders',function(){
scenario('character to right matches definition of current position',function(){
given("an input with a mask definition of '9-9'", function(){
input
.mask("9-9")
.mashKeys("12");
});
given("the input has cursor positioned on first character", function(){
input.caret(0);
});
when("hitting the delete key",function(){
input.mashKeys(function(keys){keys.type(keys.delete)});
});
then("value should be correct",function(){
expect(input).toHaveValue('2-_');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
scenario('character to right does not match definition of current position',function(){
given("an input with a mask definition of '9-9'", function(){
input
.mask("9-a")
.mashKeys("1z");
});
given("the input has cursor positioned on first character", function(){
input.caret(0);
});
when("hitting the delete key",function(){
input.mashKeys(function(keys){keys.type(keys.delete)});
});
then("value should be correct",function(){
expect(input).toHaveValue('_-z');
});
and("caret position should be correct",function(){
expect(input.caret().begin).toEqual(0);
});
});
});
});
});

View File

@@ -0,0 +1,23 @@
feature("Escape Key", function() {
story('User presses escape key after typing in some changes',function(){
scenario('mask is applied with an existing value',function(){
given("an input an existing value '6'", function(){
input
.val('6');
});
given("a mask definition of '9'", function(){
input
.mask('9').focus();
});
waits(1);
when("user types something different then hits escape key",function(){
input.mashKeys(function(keys){keys.type('1',keys.esc)});
});
then("value is return to previous value",function(){
expect(input).toHaveValue('6');
});
});
});
});

View File

@@ -0,0 +1,105 @@
feature("Focusing A Masked Input",function(){
scenario("Mask starts with a placeholder",function(){
given("a mask beginning with a placeholder",function(){
input.mask("9");
});
when("focusing",function(){
input.focus();
});
waits(20);
then("placeholder text should be correct",function(){
expect(input).toHaveValue('_');
});
and("caret position should be correct",function(){
var caret=input.caret();
expect(caret.begin).toEqual(0);
expect(caret.end).toEqual(0);
});
});
scenario("Mask starts with a literal",function(){
given("a mask beginning with a literal",function(){
input.mask("(9)");
});
when("focusing",function(){
input.focus();
});
waits(20);
then("placeholder text should be correct",function(){
expect(input).toHaveValue('(_)');
});
and("caret position should be correct",function(){
var caret=input.caret();
expect(caret.begin).toEqual(1);
expect(caret.end).toEqual(1);
});
});
scenario("Masking a hidden input",function(){
var error;
$(window).on("error.test",function(err){error=err;})
given("a mask on a hidden input",function(){
input.hide().mask("9");
});
when("focusing input",function(){
input.focus();
});
waits(1);
then("should not throw an error",function(){
expect(error).toBeUndefined();
})
});
});
feature("Leaving A Masked Input",function(){
scenario("All placeholders filled",function(){
given("a mask with two placeholders",function(){
input.mask("99");
});
when("typing two characters and blurring",function(){
input.mashKeys("12").blur();
});
then("value should be correct",function(){
expect(input).toHaveValue("12");
});
});
scenario("Empty placeholders remaining",function(){
given("a mask with two placeholders",function(){
input.mask("99");
});
when("typing one character and blurring",function(){
input.mashKeys("1").blur();
});
then("value should be empty",function(){
expect(input).toHaveValue("");
});
});
});
feature("Optional marker",function(){
scenario("Placeholders not filled to marker",function(){
given("a mask with an optional marker",function(){
input.mask("99?99");
});
when("typing one character and leaving",function(){
input.mashKeys("1").blur();
});
then("value should be empty",function(){
expect(input).toHaveValue("");
});
});
scenario("Placeholders filled to marker",function(){
given("a mask with an optional marker",function(){
input.mask("99?99");
});
when("typing two characters and leaving",function(){
input.mashKeys("12").blur();
});
then("value should remain",function(){
expect(input).toHaveValue("12");
});
});
});

View File

@@ -0,0 +1,16 @@
feature("Pasting", function() {
scenario('When pasting a value',function(){
var completed=false;
given("an input with a completed callback", function(){
input.mask("99",{completed:function(){completed=true;}});
});
when("pasting",function(){
input.val("99").trigger("paste").trigger("input");
});
waits(1);
then("completed callback should be called",function(){
expect(completed).toBeTruthy();
});
});
});

View File

@@ -0,0 +1,57 @@
feature("Getting raw value",function(){
scenario("After typing",function(){
given("an input with a mask containing a literal", function(){
input
.mask("9/9");
});
when("typing all numbers",function(){
input.mashKeys("12");
});
then("raw value should be correct",function(){
expect(input.mask()).toEqual("12");
});
});
scenario("While typing",function(){
given("an input with a mask containing a literal", function(){
input
.mask("9/9");
});
when("typing a number",function(){
input.mashKeys("1");
});
then("raw value should be correct",function(){
expect(input.mask()).toEqual("1");
});
});
scenario("Before typing",function(){
given("an input with a mask containing a literal", function(){
input
.mask("9/9");
});
then("raw value should be correct",function(){
expect(input.mask()).toEqual("");
});
});
scenario("After typing partial input past an optional marker",function(){
given("an input with a mask containing a literal", function(){
input
.mask("9?99");
});
when("typing a partial input",function(){
input.mashKeys("12");
});
then("raw value should be correct",function(){
expect(input.mask()).toEqual("12");
});
});
});

View File

@@ -0,0 +1,18 @@
feature("Masking an Input", function() {
scenario('Applying a mask to an already masked input',function(){
given("an input with two masks", function(){
input
.mask("9")
.mask("99");
});
when("typing a number",function(){
input.mashKeys("1");
});
then("value should be correct",function(){
expect(input).toHaveValue('1_');
});
});
});

View File

@@ -0,0 +1,68 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Masked Input Plugin Tests</title>
<!--Jasmine-->
<link rel="stylesheet" type="text/css" href="lib/jasmine/jasmine.css">
<script type="text/javascript" src="lib/jasmine/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine/jasmine-html.js"></script>
<!--Jasmine Species-->
<link rel="stylesheet" type="text/css" href="lib/jasmine-species/calm.css">
<script type="text/javascript" src="lib/jasmine-species/jasmine-grammar.js"></script>
<script type="text/javascript" src="lib/jasmine-species/jasmine-reporting.js"></script>
<!--My Stuff-->
<script type="text/javascript" src="lib/matchers.js"></script>
<script type="text/javascript">
function importGrammar(g){
for (var prop in g) {
if (g.hasOwnProperty(prop))
window[prop] = g[prop];
}
}
importGrammar(jasmine.grammar.FeatureStory);
importGrammar(jasmine.grammar.GWT);
var input;
beforeEach(function(){ input = $("<input />").appendTo("body").focus(); });
afterEach(function(){ input.remove();});
</script>
<!-- include source files here... -->
<script type="text/javascript" src="../lib/jquery-1.9.0.min.js"></script>
<script type="text/javascript" src="lib/jquery.keymasher.js"></script>
<script type="text/javascript" src="../dist/jquery.maskedinput.min.js"></script>
<!-- Specs -->
<script type="text/javascript" src="Setup.Spec.js"></script>
<script type="text/javascript" src="Raw.Spec.js"></script>
<script type="text/javascript" src="Focus.Spec.js"></script>
<script type="text/javascript" src="Typing.Spec.js"></script>
<script type="text/javascript" src="Backspace.Spec.js"></script>
<script type="text/javascript" src="Delete.Spec.js"></script>
<script type="text/javascript" src="Escape.Spec.js"></script>
<script type="text/javascript" src="Paste.Spec.js"></script>
</head>
<body>
<script type="text/javascript">
var jasmineEnv = jasmine.getEnv();
var styledReporter = new jasmine.reporting.StyledHtmlReporter();
jasmineEnv.addReporter(styledReporter);
jasmineEnv.specFilter = function(spec) {
return styledReporter.specFilter(spec);
};
jasmine.getEnv().execute();
</script>
</body>
</html>

View File

@@ -0,0 +1,58 @@
describe("Typing Specifications", function() {
describe("with caret position to the left of a character",function(){
describe("when character to right matches the next mask definition",function(){
beforeEach(function(){
runs(function(){
input
.mask("99")
.focus()
});
waits(1);
runs(function(){
input
.mashKeys("1")
.caret(0)
.mashKeys("2");
});
})
it("should shift character to the right",function(){
expect(input).toHaveValue("21");
});
it("should have correct caret position",function(){
var caret=input.caret();
expect(caret.begin).toEqual(1);
expect(caret.end).toEqual(1);
});
});
describe("when character to right does not match the next mask definition",function(){
beforeEach(function(){
runs(function(){
input
.mask("9a")
.focus()
});
waits(1);
runs(function(){
input
.mashKeys("1")
.caret(0)
.mashKeys("2");
});
})
it("should overwrite character",function(){
expect(input).toHaveValue("2_");
});
it("should have correct caret position",function(){
var caret=input.caret();
expect(caret.begin).toEqual(1);
expect(caret.end).toEqual(1);
});
});
});
});

View File

@@ -0,0 +1,24 @@
Copyright (c) 2010-2011, Rudy Lattae
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Rudy Lattae nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Rudy Lattae BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,106 @@
/**
* Calm theme for the jasmine-bloom StyledHtmlReporter output.
*
* This theme does away with the default boxey look. The resulting report
* is a lot less "busy" thus making it easy to focus on your specs.
*/
/* jasmine-reporter style overrides for */
.jasmine_reporter a { text-decoration:none; }
.jasmine_reporter > .suite {
padding-bottom: 0.3em;
margin-bottom: 0.3em;
border-bottom: solid 2px #eee; }
.banner, .runner {
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px; }
.runner {
-webkit-box-shadow: 2px 2px 3px #888;
-moz-box-shadow: 2px 2px 3px #888;
box-shadow: 2px 2px 5px #888; }
.suite {
border: none;
padding-left: 0.5em; }
.suite.failed,
.suite.passed,
.suite.skipped {
background: transparent; }
.suite.passed > a {
color: green; }
.suite.failed > a {
color: #c11b17; }
.suite.skipped > a {
color: #aaa; }
.suite > .description {
font-weight: bold; }
.suite.step > .description {
font-weight: normal; }
.spec {
margin: 0px;
border: none;
padding-left: 0.5em;
margin-left: 0.5em;
margin-top: 0.2em; }
.spec.failed,
.spec.passed,
.spec.skipped {
background: transparent;
border: none;
padding-bottom: 0.2em; }
.spec.failed a {
color: #c11b17; }
.spec.passed a {
color: green; }
.spec.skipped a {
color: #ccc; }
.spec:hover {
background-color: #eee;
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px; }
.spec .description {
padding-left: 0.5em; }
.messages {
border: none;
margin-left: 1em;
padding-bottom: 0.5em; }
.jasmine_reporter .summary ul {
font-size: 0.9em;
color: #333;
padding-left: 0.2em;
margin: 0 0.5em; }
.jasmine_reporter .summary li {
list-style: none; }
.jasmine_reporter .details ul {
font-size: 0.8em;
color: #777;
padding-left: 0.2em;
margin: 0 0.8em; }
.jasmine_reporter .details li {
list-style: none; }
/* header style (if header is used) */
.header {
margin: 0 5px; }
.header h1 {
font-size: 1.3em; }
.header ul.menu {
margin: 0 0 0.5em 0;
padding: 0.3em;
background-color: #eee; }
.header ul.menu li {
display: inline;
list-style-type: none;
margin-right: 1em; }

View File

@@ -0,0 +1,233 @@
/**
* Jasmine Grammar - Additional Jasmine grammar to enable alternate BDD approaches.
*
* Copyright (C) 2010-2011, Rudy Lattae
* License: Simplified BSD
*
* Jasmine-Grammar contains some additions to the jasmine api that make it
* more suitable to alternate BDD approaches. The end-goal is streamline the
* grammatical aspect of specing out an application from different view-points.
*
* The new grammar should make it easier to create other types of specifications
* apart from "describe" and "it should". They are simply wrappers
* for "describe" and "it" so they follow the same rules for nesting.
*/
// Top level namespace for the package
jasmine.grammar = (typeof jasmine.grammar === 'undefined') ? {} : jasmine.grammar;
/**
* Feature / Story => Scenario => ... style grammar
*/
jasmine.grammar.FeatureStory = {
/**
* Defines a suite tagged as a "feature"
*/
feature: function(description, specDefinitions) {
var suite = jasmine.grammar.getEnv().describe('Feature: ' + description, specDefinitions);
suite.tags = ['feature'];
return suite;
},
/**
* Defines a suite tagged as a "story"
*/
story: function(description, specDefinitions) {
var suite = jasmine.grammar.getEnv().describe('Story: ' + description, specDefinitions);
suite.tags = ['story'];
return suite;
},
/**
* Defines a suite tagged as a "component"
*/
component: function(description, specDefinitions) {
var suite = jasmine.grammar.getEnv().describe('Component: ' + description, specDefinitions);
suite.tags = ['component'];
return suite;
},
/**
* Defines a spec marked as a "scenario"
*/
scenario: function(desc, func) {
return jasmine.grammar.getEnv().it('Scenario: ' + desc, func);
}
};
/**
* Given => When => Then ... style grammar
*/
jasmine.grammar.GWT = {
/**
* Defines a "given" step as a runs block that marks the beginning of a GWT chain
*/
given: function(desc, func) {
return this._addStepToCurrentSpec('Given ' + desc, func);
},
/**
* Defines a "when" step as a runs block that marks the interesting event in a GWT chain
*/
when: function(desc, func) {
return this._addStepToCurrentSpec('When ' + desc, func);
},
/**
* Defines a "then" step as a runs block that marks the conclusion of a Given, when, then construct
*/
then: function(desc, func) {
return this._addStepToCurrentSpec('Then ' + desc, func);
},
/**
* Defines an "and" step as a runs block that is a continuation from a "then" statement
*/
and: function(desc, func) {
return this._addStepToCurrentSpec('And ' + desc, func);
},
/**
* Defines a "but" step as a runs block that is a continuation from a "then" statement
*/
but: function(desc, func) {
return this._addStepToCurrentSpec('But ' + desc, func);
},
/**
* Adds the given function as a step (runs block) in the current spec. Also adds the description to the details list of the spec
*/
_addStepToCurrentSpec: function(desc, func) {
var spec = jasmine.grammar.getEnv().currentSpec;
spec.details = spec.details || [];
spec.details.push(desc);
spec.runs(func);
return spec;
}
};
/**
* Concern => Context => Specification style grammar
*/
jasmine.grammar.ContextSpecification = {
/**
* Defines a suite tagged as a "concern"
*/
concern: function(description, specDefinitions) {
var suite = jasmine.grammar.getEnv().describe(description, specDefinitions);
suite.tags = ['concern'];
return suite;
},
/**
* Defines a suite tagged as a "context"
*/
context: function(description, specDefinitions) {
var suite = jasmine.grammar.getEnv().describe(description, specDefinitions);
suite.tags = ['context'];
return suite;
},
/**
* Defines a simple spec -- similar to it
*/
spec: function(desc, func) {
return jasmine.grammar.getEnv().it(desc, func);
}
}
/**
* Executable docs (Topic => Example) style grammar
*/
jasmine.grammar.XDoc = {
/**
* Defines a suite tagged as a "topic"
*/
topic: function(description, specDefinitions) {
var suite = jasmine.grammar.getEnv().describe(description, specDefinitions);
suite.tags = ['topic'];
return suite;
},
/**
* Defines a suite tagged as an "example".
*
* An axample suite actually stores the inner suites as a string in the "defs" attribute
*/
example: function(description, specDefinitions) {
var suite = jasmine.grammar.getEnv().describe(description, specDefinitions);
suite.tags = ['example'];
suite.expose = true;
suite.defs = specDefinitions.toString()
.replace(/^function.*\(.*\).*{/, '')
.replace(/}$/, '').trim(); // stored for later output
return suite;
},
/**
* Defines a simple spec without any associated function
*/
pass: function(desc, func) {
return jasmine.grammar.getEnv().it(desc);
}
};
/**
* Some more useful constructs that attach metadata to suites and specs
*/
jasmine.grammar.Meta = {
/**
* Adds summary content to the current suite.
*
* @param {String} content(s) variable number of detail content
* @see jasmine.grammar.SuiteDetails
*/
summary: function() {
var suite = jasmine.grammar.getEnv().currentSuite;
suite.summary = suite.summary || [];
if (arguments.length > 0) {
for(i=0; i<arguments.length; i++) {
suite.summary.push(arguments[i]);
}
}
},
/**
* Adds detail entries in the current spec.
*
* @param {String} content(s) variable number of detail content
* @see jasmine.grammar.SuiteDetails
*/
details: function() {
var spec = jasmine.grammar.getEnv().currentSpec;
spec.details = spec.details || [];
if (arguments.length > 0) {
for(i=0; i<arguments.length; i++) {
spec.details.push(arguments[i]);
}
}
}
};
// Utilities
// =========
/**
* Getter for the Jasmine environment. Makes it possible to inject a different environment when necessary.
*/
jasmine.grammar.getEnv = function() {
return jasmine.grammar._currentEnv = jasmine.grammar._currentEnv || jasmine.getEnv();
};

View File

@@ -0,0 +1,191 @@
/**
* Jasmine Reporting - Companion reporting with metadata output for your
* Jasmine specs with extended grammar
*
* Copyright (C) 2010-2011, Rudy Lattae
* License: Simplified BSD
*/
// Top level namespace for the package
jasmine.reporting = (typeof jasmine.reporting === 'undefined') ? {} : jasmine.reporting;
/**
* The StyledHtmlReporter provides augments the jasmine.TrivialReporter
*
* It outputs additional meta-data relating to your specs to streamline
* the presentation of the spec report. When used in conjunction with the
* the alternate BDD grammar, your Html report is much easier on the eyes.
*/
jasmine.reporting.StyledHtmlReporter = function(doc) {
this.document = doc || document;
this.suiteDivs = {};
this.logRunningSpecs = false;
};
jasmine.reporting.StyledHtmlReporter.prototype = new jasmine.TrivialReporter();
jasmine.reporting.StyledHtmlReporter.prototype.constructor = jasmine.reporting.StyledHtmlReporter;
jasmine.reporting.StyledHtmlReporter.prototype.reportRunnerStarting = function(runner) {
var showPassed, showSkipped;
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
this.createDom('div', { className: 'banner' },
this.createDom('div', { className: 'logo' },
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
this.createDom('span', { className: 'version' }, runner.env.versionString())),
this.createDom('div', { className: 'options' },
"Show ",
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
)
),
this.runnerDiv = this.createDom('div', { className: 'runner running' },
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
);
this.document.body.appendChild(this.outerDiv);
var suites = runner.suites();
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
var suiteTags = (typeof suite.tags === 'undefined') ? '' : ' ' + suite.tags.join(' ');
var suiteDiv = this.createDom('div', { className: 'suite' + suiteTags },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
if (suite.summary) {
suiteDiv.appendChild(this.createDom('div', {className: 'summary'}, this.createDomFromListOrString(suite.summary)));
}
if (suite.expose) {
suiteDiv.appendChild(this.createDom('pre', {}, suite.defs));
}
this.suiteDivs[suite.id] = suiteDiv;
var parentDiv = this.outerDiv;
if (suite.parentSuite) {
parentDiv = this.suiteDivs[suite.parentSuite.id];
}
parentDiv.appendChild(suiteDiv);
}
this.startedAt = new Date();
var self = this;
showPassed.onchange = function(evt) {
if (evt.target.checked) {
self.outerDiv.className += ' show-passed';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
}
};
showSkipped.onchange = function(evt) {
if (evt.target.checked) {
self.outerDiv.className += ' show-skipped';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
}
};
};
jasmine.reporting.StyledHtmlReporter.prototype.reportSuiteResults = function(suite) {
var results = suite.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.totalCount == 0 && (!status == 'failed' || !suite.isIntermediate)) { // todo: change this to check results.skipped
status = 'skipped';
}
this.suiteDivs[suite.id].className += " " + status;
};
jasmine.reporting.StyledHtmlReporter.prototype.reportSpecResults = function(spec) {
var results = spec.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
var specDiv = this.createDom('div', { className: 'spec ' + status },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(spec.getFullName()),
title: spec.getFullName()
}, spec.description));
if (spec.details) {
specDiv.appendChild(this.createDom('div', {className: 'details'}, this.createDomFromListOrString(spec.details)));
}
var resultItems = results.getItems();
var messagesDiv = this.createDom('div', { className: 'messages' });
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
if (result.type == 'log') {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
} else if (result.type == 'expect' && result.passed && !result.passed()) {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
if (result.trace.stack) {
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
}
}
}
if (messagesDiv.childNodes.length > 0) {
specDiv.appendChild(messagesDiv);
}
this.suiteDivs[spec.suite.id].appendChild(specDiv);
};
/**
* Creates the proper dom element for the given data object.
*
* If the data is a simple string, the element created is a "p".
* If the data is a list, the element created is an unordered list.
* The tags are rendered to the class attribute on the dom element created
*/
jasmine.reporting.StyledHtmlReporter.prototype.createDomFromListOrString = function(data, tags) {
var classAttrs = '';
if (typeof tags !== 'undefined') {
classAttrs = (tags instanceof Array) ? tags.join(' ') : tags;
}
if (data instanceof Array) {
return this.createDomList('ul', ((classAttrs == '') ? {} : { className: classAttrs}), data);
}
return this.createDom('p', { className: classAttrs}, data);
}
/**
* Creates dom element with the suite defs as content
*/
jasmine.reporting.StyledHtmlReporter.prototype.createDomFromSuiteDefs = function(defs) {
var classAttrs = '';
if (typeof defs !== 'undefined') {
return this.createDom('p', {}, defs);
}
}
/**
* Creates a list of 'li' elements given an array
*/
jasmine.reporting.StyledHtmlReporter.prototype.createDomList = function(type, attrs, items) {
var list;
if (typeof items !== 'undefined' && items.length > 0) {
list = this.createDom(type, attrs);
for (var i = 0; i < items.length; i++) {
list.appendChild(this.createDom('li', {}, items[i]));
}
}
return list;
};

View File

@@ -0,0 +1 @@
{"version": "0.8.5b"}

View File

@@ -0,0 +1,20 @@
Copyright (c) 2008-2010 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,188 @@
jasmine.TrivialReporter = function(doc) {
this.document = doc || document;
this.suiteDivs = {};
this.logRunningSpecs = false;
};
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
var el = document.createElement(type);
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
if (child) { el.appendChild(child); }
}
}
for (var attr in attrs) {
if (attr == "className") {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
};
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
var showPassed, showSkipped;
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
this.createDom('div', { className: 'banner' },
this.createDom('div', { className: 'logo' },
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
this.createDom('span', { className: 'version' }, runner.env.versionString())),
this.createDom('div', { className: 'options' },
"Show ",
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
)
),
this.runnerDiv = this.createDom('div', { className: 'runner running' },
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
);
this.document.body.appendChild(this.outerDiv);
var suites = runner.suites();
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
var suiteDiv = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
this.suiteDivs[suite.id] = suiteDiv;
var parentDiv = this.outerDiv;
if (suite.parentSuite) {
parentDiv = this.suiteDivs[suite.parentSuite.id];
}
parentDiv.appendChild(suiteDiv);
}
this.startedAt = new Date();
var self = this;
showPassed.onclick = function(evt) {
if (showPassed.checked) {
self.outerDiv.className += ' show-passed';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
}
};
showSkipped.onclick = function(evt) {
if (showSkipped.checked) {
self.outerDiv.className += ' show-skipped';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
}
};
};
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
var results = runner.results();
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
this.runnerDiv.setAttribute("class", className);
//do it twice for IE
this.runnerDiv.setAttribute("className", className);
var specs = runner.specs();
var specCount = 0;
for (var i = 0; i < specs.length; i++) {
if (this.specFilter(specs[i])) {
specCount++;
}
}
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
};
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
var results = suite.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.totalCount == 0) { // todo: change this to check results.skipped
status = 'skipped';
}
this.suiteDivs[suite.id].className += " " + status;
};
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
if (this.logRunningSpecs) {
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
}
};
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
var results = spec.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
var specDiv = this.createDom('div', { className: 'spec ' + status },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(spec.getFullName()),
title: spec.getFullName()
}, spec.description));
var resultItems = results.getItems();
var messagesDiv = this.createDom('div', { className: 'messages' });
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
if (result.type == 'log') {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
} else if (result.type == 'expect' && result.passed && !result.passed()) {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
if (result.trace.stack) {
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
}
}
}
if (messagesDiv.childNodes.length > 0) {
specDiv.appendChild(messagesDiv);
}
this.suiteDivs[spec.suite.id].appendChild(specDiv);
};
jasmine.TrivialReporter.prototype.log = function() {
var console = jasmine.getGlobal().console;
if (console && console.log) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
}
}
};
jasmine.TrivialReporter.prototype.getLocation = function() {
return this.document.location;
};
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
var paramMap = {};
var params = this.getLocation().search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
if (!paramMap["spec"]) return true;
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
};

View File

@@ -0,0 +1,166 @@
body {
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
}
.jasmine_reporter a:visited, .jasmine_reporter a {
color: #303;
}
.jasmine_reporter a:hover, .jasmine_reporter a:active {
color: blue;
}
.run_spec {
float:right;
padding-right: 5px;
font-size: .8em;
text-decoration: none;
}
.jasmine_reporter {
margin: 0 5px;
}
.banner {
color: #303;
background-color: #fef;
padding: 5px;
}
.logo {
float: left;
font-size: 1.1em;
padding-left: 5px;
}
.logo .version {
font-size: .6em;
padding-left: 1em;
}
.runner.running {
background-color: yellow;
}
.options {
text-align: right;
font-size: .8em;
}
.suite {
border: 1px outset gray;
margin: 5px 0;
padding-left: 1em;
}
.suite .suite {
margin: 5px;
}
.suite.passed {
background-color: #dfd;
}
.suite.failed {
background-color: #fdd;
}
.spec {
margin: 5px;
padding-left: 1em;
clear: both;
}
.spec.failed, .spec.passed, .spec.skipped {
padding-bottom: 5px;
border: 1px solid gray;
}
.spec.failed {
background-color: #fbb;
border-color: red;
}
.spec.passed {
background-color: #bfb;
border-color: green;
}
.spec.skipped {
background-color: #bbb;
}
.messages {
border-left: 1px dashed gray;
padding-left: 1em;
padding-right: 1em;
}
.passed {
background-color: #cfc;
/*display: none;*/
}
.failed {
background-color: #fbb;
}
.skipped {
color: #777;
background-color: #eee;
display: none;
}
/*.resultMessage {*/
/*white-space: pre;*/
/*}*/
.resultMessage span.result {
display: block;
line-height: 2em;
color: black;
}
.resultMessage .mismatch {
color: black;
}
.stackTrace {
white-space: pre;
font-size: .8em;
margin-left: 10px;
max-height: 5em;
overflow: auto;
border: 1px inset red;
padding: 1em;
background: #eef;
}
.finished-at {
padding-left: 1em;
font-size: .6em;
}
.show-passed .passed,
.show-skipped .skipped {
display: block;
}
#jasmine_content {
position:fixed;
right: 100%;
}
.runner {
border: 1px solid gray;
display: block;
margin: 5px 0;
padding: 2px 0 2px 10px;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
/*
Key Masher plugin for jQuery (https://github.com/digitalBush/jquery.keymasher)
Copyright (c) 2010-2013 Josh Bush (digitalbush.com)
Licensed under the MIT license
Version: 0.3
*/
(function($,undefined){
//numberPad={'0':96,'1':97,'2':98,'3':99,'4':100,'5':101,'6':102,'7':103,'8':104,'9':105,'*':106,'+':107,'-':109,'.':110,'/':111},
var keys=(function(){
var defs={},
keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`-=[]\\;',./ \t\n",
shifted = "abcdefghijklmnopqrstuvwxyz!@#$%^&*()~_+{}|:\"<>?",
noprint={shift:16,ctrl:17,meta:91,alt:18,f1:112,f2:113,f3:114,f4:115,f5:116,f6:117,f7:118,f8:119,f9:120,f10:121,f11:122,f12:123,
capslock:20,numlock:144,scrolllock:145,pageup:33,pagedown:34,end:35,home:36,backspace:8,
insert:45, 'delete':46,pause:19,esc:27,left:37,up:38,right:39,down:40,printscreen:44};
$.each(keys.split(''),function(index,value){
var keyCode=value.charCodeAt(0),shift=shifted[index];
defs[value]={keyCode:keyCode,charCode:keyCode,shift:shift};
if(shift)
defs[shift]={keyCode:keyCode,charCode:shift.charCodeAt(0),shift:value,requiresShift:index>=26};
});
$.each(noprint,function(key,value){defs[key]={keyCode:value};});
return defs;
})();
var KeyMasher=function(elm){
var modifierState={alt: false, ctrl: false, meta: false, shift: false},
forced={};
var queueModifierEvent=function(direction,modifier,isForced){
forced[modifier]=isForced;
modifierState[modifier]=(direction=='down');
var event=$.extend($.Event(), modifierState, {type:'key'+direction, keyCode: keys[modifier].keyCode, charCode: 0});
elm.trigger(event);
};
var queueStroke=function(key){
if($.type(key)==='string')
key=keys[key];
if(key.requiresShift && !modifierState.shift)
queueModifierEvent('down','shift',true);
else if(modifierState.shift && key.shift)
key=keys[key.shift];
var ignore = !key.charCode || modifierState.alt || modifierState.ctrl || modifierState.meta,
down = $.extend($.Event('keydown'), modifierState, {keyCode: key.keyCode, charCode: 0, which:key.keyCode}),
press = $.extend($.Event('keypress'), modifierState, {keyCode: key.charCode, charCode: key.charCode, which: key.charCode}),
up = $.extend($.Event('keyup'), modifierState, {keyCode: key.keyCode, charCode: 0, which:key.keyCode});
elm.trigger(down);
if(!down.isDefaultPrevented() && !ignore){
elm.trigger(press);
if(!press.isDefaultPrevented()){
//need to do caret positioning
elm.val(elm.val()+String.fromCharCode(key.charCode));
}
}
elm.trigger(up);
if(forced.shift)
queueModifierEvent('up','shift');
};
var public={
hold:function(holding,typing){
var toks=holding.split(',');
$.each(toks,function(index,value){queueModifierEvent('down',value);});
public.type(typing);
$.each(toks,function(index,value){queueModifierEvent('up',value);});
return public;
},
type:function(){
$.each(arguments,function(index,typing){
if($.type(typing)==='string')
$.each(typing.split(''),function(index,value){queueStroke(value);});
else
queueStroke(typing);
});
return public;
}
};
return $.extend(public,keys);
};
$.fn.mashKeys=function(fn){
if($.type(fn)==='string'){
var typing=fn;
fn=function(keys){keys.type(typing)};
}
return this.each(function(){
fn(KeyMasher($(this)));
});
};
})(jQuery);

View File

@@ -0,0 +1,16 @@
beforeEach(function(){
this.addMatchers({
toHaveValue:function(expected){
return (this.actual=this.actual.val())===expected;
},
toMatchPropertiesOf:function(expected){
if($.type(expected)!=='object')
return false;
for(var prop in expected){
if(this.actual[prop]!==expected[prop])
return false;
}
return true;
}
});
});