Skip to content

Instantly share code, notes, and snippets.

@stemcstudio
Last active May 24, 2024 15:52
Show Gist options
  • Save stemcstudio/5809fc601294b38a725bd4e8b0537313 to your computer and use it in GitHub Desktop.
Save stemcstudio/5809fc601294b38a725bd4e8b0537313 to your computer and use it in GitHub Desktop.
Operator Overloading

Operator Overloading

Overview

This example illustrates operator overloading using a Complex number class.

For further description of operator overloading in STEMCstudio, please see the STEMCstudio Wiki.

import { Complex } from './Complex'
export function complexSpec() {
describe("constructor", function() {
const x = Math.random()
const y = Math.random()
const z = new Complex(x, y)
it("should preserve real argument", function() {
expect(z.real).toBe(x)
})
it("should preserve imag argument", function() {
expect(z.imag).toBe(y)
})
})
describe("Complex + Complex", function() {
const z1 = new Complex(2, 3)
const z2 = new Complex(5, 7)
const z = z1 + z2
it("should sum real argument", function() {
expect(z.real).toBe(z1.real + z2.real)
})
it("should sum imag argument", function() {
expect(z.imag).toBe(z1.imag + z2.imag)
})
})
describe("Complex + number", function() {
const z1 = new Complex(2, 3)
const z2 = 5
const z = z1 + z2
it("should sum real argument", function() {
expect(z.real).toBe(z1.real + z2)
})
it("should sum imag argument", function() {
expect(z.imag).toBe(z1.imag)
})
})
describe("number + Complex", function() {
const z1 = 2
const z2 = new Complex(5, 7)
const z = z1 + z2
it("should sum real argument", function() {
expect(z.real).toBe(z1 + z2.real)
})
it("should sum imag argument", function() {
expect(z.imag).toBe(z2.imag)
})
})
describe("Complex * Complex", function() {
const z1 = new Complex(2, 3)
const z2 = new Complex(5, 7)
const z = z1 * z2
it("should sum real argument", function() {
expect(z.real).toBe(z1.real * z2.real - z1.imag * z2.imag)
})
it("should sum imag argument", function() {
expect(z.imag).toBe(z1.real * z2.imag + z1.imag * z2.real)
})
})
describe("Complex * number", function() {
const z1 = new Complex(2, 3)
const z2 = 5
const z = z1 * z2
it("should sum real argument", function() {
expect(z.real).toBe(z1.real * z2)
})
it("should sum imag argument", function() {
expect(z.imag).toBe(z1.imag * z2)
})
})
describe("number * Complex", function() {
const z1 = 2
const z2 = new Complex(5, 7)
const z = z1 * z2
it("should sum real argument", function() {
expect(z.real).toBe(z1 * z2.real)
})
it("should sum imag argument", function() {
expect(z.imag).toBe(z1 * z2.imag)
})
})
describe("-Complex", function() {
const z1 = new Complex(2, 3)
const z = -z1
it("should negate real argument", function() {
expect(z.real).toBe(z1.real * -1)
})
it("should negate imag argument", function() {
expect(z.imag).toBe(z1.imag * -1)
})
})
}
export class Complex {
constructor(public readonly real: number, public readonly imag: number) {
}
__add__(rhs: Complex | number): Complex | undefined {
if (typeof rhs === 'number') {
return new Complex(this.real + rhs, this.imag)
}
else if (rhs instanceof Complex) {
return new Complex(this.real + rhs.real, this.imag + rhs.imag)
}
else {
return void 0
}
}
__radd__(lhs: number): Complex | undefined {
if (typeof lhs === 'number') {
return new Complex(lhs + this.real, this.imag)
}
else {
return void 0
}
}
__mul__(rhs: Complex | number): Complex | undefined {
if (typeof rhs === 'number') {
return new Complex(this.real * rhs, this.imag * rhs)
}
else if (rhs instanceof Complex) {
const x = this.real * rhs.real - this.imag * rhs.imag
const y = this.real * rhs.imag + this.imag * rhs.real
return new Complex(x, y)
}
else {
return void 0
}
}
__rmul__(lhs: number): Complex | undefined {
if (typeof lhs === 'number') {
return new Complex(lhs * this.real, lhs * this.imag)
}
else {
return void 0
}
}
__neg__(): Complex {
return new Complex(-this.real, -this.imag)
}
toString(): string {
return `${this.real} + ${this.imag} * i`
}
}
export function complex(x: number, y: number): Complex {
return new Complex(x, y)
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.6.0/jasmine.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.6.0/jasmine.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.6.0/jasmine-html.min.js"></script>
<script src="/vendor/davinci-mathscript@1.3.5/davinci-mathscript.min.js"></script>
<script src="/assets/js/stemcstudio-systemjs@1.0.0/system.js"></script>
</head>
<body>
<script>
System.config({
"warnings": true,
"map": {
"jasmine": "https://cdn.jsdelivr.net/npm/jasmine@3.6.0/lib/jasmine.js"
}
});
</script>
Nothing to see here, take a look at the tests
<script>
System.register('./Complex.spec.js', ['./Complex'], function(exports_1, context_1) {
'use strict';
var Complex_1;
var __moduleName = context_1 && context_1.id;
function complexSpec() {
describe('constructor', function() {
var x = Math.random();
var y = Math.random();
var z = new Complex_1.Complex(x, y);
it('should preserve real argument', function() {
expect(z.real).toBe(x);
});
it('should preserve imag argument', function() {
expect(z.imag).toBe(y);
});
});
describe('Complex + Complex', function() {
var z1 = new Complex_1.Complex(2, 3);
var z2 = new Complex_1.Complex(5, 7);
var z = Ms.add(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.add(z1.real, z2.real));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(Ms.add(z1.imag, z2.imag));
});
});
describe('Complex + number', function() {
var z1 = new Complex_1.Complex(2, 3);
var z2 = 5;
var z = Ms.add(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.add(z1.real, z2));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(z1.imag);
});
});
describe('number + Complex', function() {
var z1 = 2;
var z2 = new Complex_1.Complex(5, 7);
var z = Ms.add(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.add(z1, z2.real));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(z2.imag);
});
});
describe('Complex * Complex', function() {
var z1 = new Complex_1.Complex(2, 3);
var z2 = new Complex_1.Complex(5, 7);
var z = Ms.mul(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.sub(Ms.mul(z1.real, z2.real), Ms.mul(z1.imag, z2.imag)));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(Ms.add(Ms.mul(z1.real, z2.imag), Ms.mul(z1.imag, z2.real)));
});
});
describe('Complex * number', function() {
var z1 = new Complex_1.Complex(2, 3);
var z2 = 5;
var z = Ms.mul(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.mul(z1.real, z2));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(Ms.mul(z1.imag, z2));
});
});
describe('number * Complex', function() {
var z1 = 2;
var z2 = new Complex_1.Complex(5, 7);
var z = Ms.mul(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.mul(z1, z2.real));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(Ms.mul(z1, z2.imag));
});
});
describe('-Complex', function() {
var z1 = new Complex_1.Complex(2, 3);
var z = Ms.neg(z1);
it('should negate real argument', function() {
expect(z.real).toBe(Ms.mul(z1.real, Ms.neg(1)));
});
it('should negate imag argument', function() {
expect(z.imag).toBe(Ms.mul(z1.imag, Ms.neg(1)));
});
});
}
exports_1('complexSpec', complexSpec);
return {
setters: [function(Complex_1_1) {
Complex_1 = Complex_1_1;
}],
execute: function() {}
};
});
System.register('./Complex.js', [], function(exports_1, context_1) {
'use strict';
var Complex;
var __moduleName = context_1 && context_1.id;
function complex(x, y) {
return new Complex(x, y);
}
exports_1('complex', complex);
return {
setters: [],
execute: function() {
Complex = function() {
function Complex(real, imag) {
this.real = real;
this.imag = imag;
}
Complex.prototype.__add__ = function(rhs) {
if (Ms.eq(typeof rhs, 'number')) {
return new Complex(Ms.add(this.real, rhs), this.imag);
} else if (rhs instanceof Complex) {
return new Complex(Ms.add(this.real, rhs.real), Ms.add(this.imag, rhs.imag));
} else {
return void 0;
}
};
Complex.prototype.__radd__ = function(lhs) {
if (Ms.eq(typeof lhs, 'number')) {
return new Complex(Ms.add(lhs, this.real), this.imag);
} else {
return void 0;
}
};
Complex.prototype.__mul__ = function(rhs) {
if (Ms.eq(typeof rhs, 'number')) {
return new Complex(Ms.mul(this.real, rhs), Ms.mul(this.imag, rhs));
} else if (rhs instanceof Complex) {
var x = Ms.sub(Ms.mul(this.real, rhs.real), Ms.mul(this.imag, rhs.imag));
var y = Ms.add(Ms.mul(this.real, rhs.imag), Ms.mul(this.imag, rhs.real));
return new Complex(x, y);
} else {
return void 0;
}
};
Complex.prototype.__rmul__ = function(lhs) {
if (Ms.eq(typeof lhs, 'number')) {
return new Complex(Ms.mul(lhs, this.real), Ms.mul(lhs, this.imag));
} else {
return void 0;
}
};
Complex.prototype.__neg__ = function() {
return new Complex(Ms.neg(this.real), Ms.neg(this.imag));
};
Complex.prototype.toString = function() {
return ''.concat(this.real, ' + ').concat(this.imag, ' * i');
};
return Complex;
}();
exports_1('Complex', Complex);
}
};
});
System.register('./HtmlReporter.js', [], function(exports_1, context_1) {
'use strict';
var ResultsNode, ResultsStateBuilder, HtmlReporter;
var __moduleName = context_1 && context_1.id;
function failureDom(result, reporter) {
var failure = createDom(reporter, 'div', {
className: 'jasmine-spec-detail jasmine-failed'
}, failureDescription(result, reporter.stateBuilder.currentParent, reporter), createDom(reporter, 'div', {
className: 'jasmine-messages'
}));
var messages = failure.childNodes[1];
var _M9Use = Date.now();
for (var _i = 0, _a = result.failedExpectations; Ms.lt(_i, _a.length); _i++) {
if (Ms.gt(Ms.sub(Date.now(), _M9Use), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var expectation = _a[_i];
messages.appendChild(createDom(reporter, 'div', {
className: 'jasmine-result-message'
}, expectation.message));
messages.appendChild(createDom(reporter, 'div', {
className: 'jasmine-stack-trace'
}, expectation.stack));
}
}
if (Ms.eq(result.failedExpectations.length, 0)) {
messages.appendChild(createDom(reporter, 'div', {
className: 'jasmine-result-message'
}, 'Spec has no expectations'));
}
return failure;
}
function summaryList(resultsTree, domParent, reporter) {
var specListNode;
var _JVyFL = Date.now();
for (var i = 0; Ms.lt(i, resultsTree.children.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _JVyFL), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var resultNode = resultsTree.children[i];
if (reporter.filterSpecs && Ms.bang(hasActiveSpec(resultNode))) {
continue;
}
if (Ms.eq(resultNode.type, 'suite')) {
var result = resultNode.result;
var suiteListNode = createDom(reporter, 'ul', {
className: 'jasmine-suite',
id: Ms.add('suite-', result.id)
}, createDom(reporter, 'li', {
className: Ms.add('jasmine-suite-detail jasmine-', result.status)
}, reporter.createAnchor({
href: specHref(result, reporter)
}, result.description)));
summaryList(resultNode, suiteListNode, reporter);
domParent.appendChild(suiteListNode);
}
if (Ms.eq(resultNode.type, 'spec')) {
var result = resultNode.result;
if (Ms.ne(domParent.getAttribute('class'), 'jasmine-specs')) {
specListNode = createDom(reporter, 'ul', {
className: 'jasmine-specs'
});
domParent.appendChild(specListNode);
}
var specDescription = result.description;
if (noExpectations(result)) {
specDescription = Ms.add('SPEC HAS NO EXPECTATIONS ', specDescription);
}
if (Ms.eq(result.status, 'pending') && Ms.ne(result.pendingReason, '')) {
specDescription = Ms.add(Ms.add(specDescription, ' PENDING WITH MESSAGE: '), result.pendingReason);
}
specListNode.appendChild(createDom(reporter, 'li', {
className: Ms.add('jasmine-', result.status),
id: Ms.add('spec-', result.id)
}, reporter.createAnchor({
href: specHref(result, reporter)
}, specDescription)));
}
}
}
}
function optionsMenu(config, reporter) {
var optionsMenuDom = createDom(reporter, 'div', {
className: 'jasmine-run-options'
}, createDom(reporter, 'span', {
className: 'jasmine-trigger'
}, 'Options'), createDom(reporter, 'div', {
className: 'jasmine-payload'
}, createDom(reporter, 'div', {
className: 'jasmine-stop-on-failure'
}, createDom(reporter, 'input', {
className: 'jasmine-fail-fast',
id: 'jasmine-fail-fast',
type: 'checkbox'
}), createDom(reporter, 'label', {
className: 'jasmine-label',
for: 'jasmine-fail-fast'
}, 'stop execution on spec failure')), createDom(reporter, 'div', {
className: 'jasmine-throw-failures'
}, createDom(reporter, 'input', {
className: 'jasmine-throw',
id: 'jasmine-throw-failures',
type: 'checkbox'
}), createDom(reporter, 'label', {
className: 'jasmine-label',
for: 'jasmine-throw-failures'
}, 'stop spec on expectation failure')), createDom(reporter, 'div', {
className: 'jasmine-random-order'
}, createDom(reporter, 'input', {
className: 'jasmine-random',
id: 'jasmine-random-order',
type: 'checkbox'
}), createDom(reporter, 'label', {
className: 'jasmine-label',
for: 'jasmine-random-order'
}, 'run tests in random order')), createDom(reporter, 'div', {
className: 'jasmine-hide-disabled'
}, createDom(reporter, 'input', {
className: 'jasmine-disabled',
id: 'jasmine-hide-disabled',
type: 'checkbox'
}), createDom(reporter, 'label', {
className: 'jasmine-label',
for: 'jasmine-hide-disabled'
}, 'hide disabled tests'))));
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
failFastCheckbox.checked = config.failFast ? true : false;
failFastCheckbox.onclick = function() {
reporter.navigateWithNewParam('failFast', Ms.bang(config.failFast));
};
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
throwCheckbox.checked = config.oneFailurePerSpec ? true : false;
throwCheckbox.onclick = function() {
reporter.navigateWithNewParam('throwFailures', Ms.bang(config.oneFailurePerSpec));
};
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
randomCheckbox.checked = config.random ? true : false;
randomCheckbox.onclick = function() {
reporter.navigateWithNewParam('random', Ms.bang(config.random));
};
var hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled');
hideDisabled.checked = config.hideDisabled ? true : false;
hideDisabled.onclick = function() {
reporter.navigateWithNewParam('hideDisabled', Ms.bang(config.hideDisabled));
};
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger');
var optionsPayload = optionsMenuDom.querySelector('.jasmine-payload');
var isOpen = /\bjasmine-open\b/;
optionsTrigger.onclick = function() {
if (isOpen.test(optionsPayload.className)) {
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
} else {
optionsPayload.className += ' jasmine-open';
}
};
return optionsMenuDom;
}
function failureDescription(result, suite, reporter) {
var wrapper = createDom(reporter, 'div', {
className: 'jasmine-description'
}, reporter.createAnchor({
title: result.description,
href: specHref(result, reporter)
}, result.description));
var suiteLink;
var _TMd9k = Date.now();
while (suite && suite.parent) {
if (Ms.gt(Ms.sub(Date.now(), _TMd9k), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
wrapper.insertBefore(reporter.createTextNode(' > '), wrapper.firstChild);
suiteLink = reporter.createAnchor({
href: suiteHref(suite, reporter)
}, suite.result.description);
wrapper.insertBefore(suiteLink, wrapper.firstChild);
suite = suite.parent;
}
}
return wrapper;
}
function suiteHref(suite, reporter) {
var els = [];
var _1YHv8 = Date.now();
while (suite && suite.parent) {
if (Ms.gt(Ms.sub(Date.now(), _1YHv8), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
els.unshift(suite.result.description);
suite = suite.parent;
}
}
return reporter.addToExistingQueryString('spec', els.join(' '));
}
function addDeprecationWarnings(result, reporter) {
if (result && result.deprecationWarnings) {
var _qNqOx = Date.now();
for (var i = 0; Ms.lt(i, result.deprecationWarnings.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _qNqOx), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var warning = result.deprecationWarnings[i].message;
reporter.deprecationWarnings.push(warning);
}
}
}
}
function findAnchor(selector, reporter) {
var element = find(selector, reporter, 'findAnchor');
if (element instanceof HTMLAnchorElement) {
return element;
} else {
throw new Error(''.concat(selector, ' is not an HTMLAnchorElement'));
}
}
function find(selector, reporter, _origin) {
var selectors = Ms.add('.jasmine_html-reporter ', selector);
var element = reporter.getContainer().querySelector(selectors);
if (element) {
return element;
} else {
throw new Error('Unable to find selectors '.concat(JSON.stringify(selectors)));
}
}
function clearPrior(reporter) {
try {
var oldReporter = find('', reporter, 'clearPrior');
reporter.getContainer().removeChild(oldReporter);
} catch (e) {}
}
exports_1('clearPrior', clearPrior);
function createDom(factory, type, attrs) {
var _children = [];
var _6giKl = Date.now();
for (var _i = 3; Ms.lt(_i, arguments.length); _i++) {
if (Ms.gt(Ms.sub(Date.now(), _6giKl), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
_children[_i - 3] = arguments[_i];
}
}
var el = factory.createElement(type);
var _6GnFk = Date.now();
for (var i = 3; Ms.lt(i, arguments.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _6GnFk), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var child = arguments[i];
if (Ms.eq(typeof child, 'string')) {
el.appendChild(factory.createTextNode(child));
} else {
if (child) {
el.appendChild(child);
}
}
}
}
for (var attr in attrs) {
if (Ms.eq(attr, 'className')) {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
}
function pluralize(singular, count) {
var word = Ms.eq(count, 1) ? singular : Ms.add(singular, 's');
return Ms.add(Ms.add(Ms.add('', count), ' '), word);
}
function specHref(result, reporter) {
return reporter.addToExistingQueryString('spec', result.fullName);
}
function seedHref(seed, reporter) {
return reporter.addToExistingQueryString('seed', seed);
}
function defaultQueryString(key, value) {
return Ms.add(Ms.add(Ms.add('?', key), '='), value);
}
function setMenuModeTo(mode, reporter) {
reporter.htmlReporterMain.setAttribute('class', Ms.add('jasmine_html-reporter ', mode));
}
function noExpectations(result) {
var allExpectations = Ms.add(result.failedExpectations.length, result.passedExpectations.length);
return Ms.eq(allExpectations, 0) && (Ms.eq(result.status, 'passed') || Ms.eq(result.status, 'failed'));
}
function hasActiveSpec(resultNode) {
if (Ms.eq(resultNode.type, 'spec')) {
var result = resultNode.result;
if (Ms.ne(result.status, 'excluded')) {
return true;
}
}
if (Ms.eq(resultNode.type, 'suite')) {
var j = resultNode.children.length;
var _PSpDt = Date.now();
for (var i = 0; Ms.lt(i, j); i++) {
if (Ms.gt(Ms.sub(Date.now(), _PSpDt), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
if (hasActiveSpec(resultNode.children[i])) {
return true;
}
}
}
}
return false;
}
return {
setters: [],
execute: function() {
ResultsNode = function() {
function ResultsNode(result, type, parent) {
this.result = result;
this.type = type;
this.parent = parent;
this.children = [];
}
ResultsNode.prototype.addChild = function(result, type) {
this.children.push(new ResultsNode(result, type, this));
};
ResultsNode.prototype.last = function() {
return this.children[this.children.length - 1];
};
ResultsNode.prototype.updateResult = function(result) {
this.result = result;
};
return ResultsNode;
}();
ResultsStateBuilder = function() {
function ResultsStateBuilder() {
this.topResults = new ResultsNode({
description: ''
}, 'suite', null);
this.currentParent = this.topResults;
this.specsExecuted = 0;
this.failureCount = 0;
this.pendingSpecCount = 0;
}
ResultsStateBuilder.prototype.suiteStarted = function(result) {
this.currentParent.addChild(result, 'suite');
this.currentParent = this.currentParent.last();
};
ResultsStateBuilder.prototype.suiteDone = function(result) {
this.currentParent.updateResult(result);
if (Ms.ne(this.currentParent, this.topResults)) {
this.currentParent = this.currentParent.parent;
}
if (Ms.eq(result.status, 'failed')) {
this.failureCount++;
}
};
ResultsStateBuilder.prototype.specStarted = function(_report) {};
ResultsStateBuilder.prototype.specDone = function(result) {
this.currentParent.addChild(result, 'spec');
if (Ms.ne(result.status, 'excluded')) {
this.specsExecuted++;
}
if (Ms.eq(result.status, 'failed')) {
this.failureCount++;
}
if (Ms.eq(result.status, 'pending')) {
this.pendingSpecCount++;
}
};
return ResultsStateBuilder;
}();
HtmlReporter = function() {
function HtmlReporter(options) {
this.failures = [];
this.deprecationWarnings = [];
this.stateBuilder = new ResultsStateBuilder();
this.config = function() {
return options.env && options.env.configuration() || {};
};
this.getContainer = options.getContainer;
this.createElement = options.createElement;
this.createTextNode = options.createTextNode;
this.navigateWithNewParam = options.navigateWithNewParam || function() {};
this.addToExistingQueryString = options.addToExistingQueryString || defaultQueryString;
this.filterSpecs = options.filterSpecs;
this.summary = createDom(this, 'div', {
className: 'jasmine-summary'
});
}
HtmlReporter.prototype.initialize = function() {
clearPrior(this);
this.htmlReporterMain = createDom(this, 'div', {
className: 'jasmine_html-reporter'
}, createDom(this, 'div', {
className: 'jasmine-banner'
}, this.createAnchor({
className: 'jasmine-title',
href: 'http://jasmine.github.io/',
target: '_blank'
}), createDom(this, 'span', {
className: 'jasmine-version'
}, jasmine.version)), createDom(this, 'ul', {
className: 'jasmine-symbol-summary'
}), createDom(this, 'div', {
className: 'jasmine-alert'
}), createDom(this, 'div', {
className: 'jasmine-results'
}, createDom(this, 'div', {
className: 'jasmine-failures'
})));
this.getContainer().appendChild(this.htmlReporterMain);
};
HtmlReporter.prototype.jasmineStarted = function(options) {
this.totalSpecsDefined = options.totalSpecsDefined || 0;
};
HtmlReporter.prototype.suiteStarted = function(result) {
this.stateBuilder.suiteStarted(result);
};
HtmlReporter.prototype.suiteDone = function(result) {
this.stateBuilder.suiteDone(result);
if (Ms.eq(result.status, 'failed')) {
this.failures.push(failureDom(result, this));
}
addDeprecationWarnings(result, this);
};
HtmlReporter.prototype.specStarted = function(result) {
this.stateBuilder.specStarted(result);
};
HtmlReporter.prototype.specDone = function(result) {
this.stateBuilder.specDone(result);
if (noExpectations(result)) {
var noSpecMsg = 'Spec "'.concat(result.fullName, '" has no expectations.');
if (Ms.eq(result.status, 'failed')) {
console.error(noSpecMsg);
} else {
console.warn(noSpecMsg);
}
}
if (Ms.bang(this.symbols)) {
this.symbols = find('.jasmine-symbol-summary', this, 'specDone');
}
this.symbols.appendChild(createDom(this, 'li', {
className: this.classNameFromSpecReport(result),
id: 'spec_'.concat(result.id),
title: result.fullName
}));
if (Ms.eq(result.status, 'failed')) {
this.failures.push(failureDom(result, this));
}
addDeprecationWarnings(result, this);
};
HtmlReporter.prototype.classNameFromSpecReport = function(report) {
return noExpectations(report) && Ms.eq(report.status, 'passed') ? 'jasmine-empty' : this.classNameFromStatus(report.status);
};
HtmlReporter.prototype.classNameFromStatus = function(status) {
switch (status) {
case 'excluded':
case 'passed': {
return this.config().hideDisabled ? 'jasmine-excluded-no-display' : 'jasmine-excluded';
}
case 'pending':
return 'jasmine-pending';
case 'failed':
return 'jasmine-failed';
default: {
throw new Error('classNameFromStatus(\''.concat(status, '\')'));
}
}
};
HtmlReporter.prototype.jasmineDone = function(doneResult) {
var _this = this;
var banner = find('.jasmine-banner', this, 'jasmineDone');
var alert = find('.jasmine-alert', this, 'jasmineDone');
var order = doneResult && doneResult.order;
var i;
alert.appendChild(createDom(this, 'span', {
className: 'jasmine-duration'
}, Ms.add(Ms.add('finished in ', Ms.div(doneResult.totalTime, 1000)), 's')));
banner.appendChild(optionsMenu(this.config(), this));
if (Ms.lt(this.stateBuilder.specsExecuted, this.totalSpecsDefined)) {
var skippedMessage = Ms.add(Ms.add(Ms.add(Ms.add('Ran ', this.stateBuilder.specsExecuted), ' of '), this.totalSpecsDefined), ' specs - run all');
var skippedLink = this.addToExistingQueryString('spec', '');
alert.appendChild(createDom(this, 'span', {
className: 'jasmine-bar jasmine-skipped'
}, this.createAnchor({
href: skippedLink,
title: 'Run all specs'
}, skippedMessage)));
}
var statusBarMessage = '';
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
var globalFailures = doneResult && doneResult.failedExpectations || [];
var failed = Ms.gt(Ms.add(this.stateBuilder.failureCount, globalFailures.length), 0);
if (Ms.gt(this.totalSpecsDefined, 0) || failed) {
statusBarMessage += Ms.add(Ms.add(pluralize('spec', this.stateBuilder.specsExecuted), ', '), pluralize('failure', this.stateBuilder.failureCount));
if (this.stateBuilder.pendingSpecCount) {
statusBarMessage += Ms.add(', ', pluralize('pending spec', this.stateBuilder.pendingSpecCount));
}
}
if (Ms.eq(doneResult.overallStatus, 'passed')) {
statusBarClassName += ' jasmine-passed ';
} else if (Ms.eq(doneResult.overallStatus, 'incomplete')) {
statusBarClassName += ' jasmine-incomplete ';
statusBarMessage = Ms.add(Ms.add(Ms.add('Incomplete: ', doneResult.incompleteReason), ', '), statusBarMessage);
} else {
statusBarClassName += ' jasmine-failed ';
}
if (order && order.random) {
var seedBar = createDom(this, 'span', {
className: 'jasmine-seed-bar'
}, ', randomized with seed ', this.createAnchor({
title: Ms.add('randomized with seed ', order.seed),
href: seedHref(order.seed, this)
}, order.seed));
alert.appendChild(createDom(this, 'span', {
className: statusBarClassName
}, statusBarMessage, seedBar));
} else {
alert.appendChild(createDom(this, 'span', {
className: statusBarClassName
}, statusBarMessage));
}
var errorBarClassName = 'jasmine-bar jasmine-errored';
var afterAllMessagePrefix = 'AfterAll ';
var _MXXCD = Date.now();
for (i = 0; Ms.lt(i, globalFailures.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _MXXCD), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
alert.appendChild(createDom(this, 'span', {
className: errorBarClassName
}, globalFailureMessage(globalFailures[i])));
}
}
function globalFailureMessage(failure) {
if (Ms.eq(failure.globalErrorType, 'load')) {
var prefix = Ms.add('Error during loading: ', failure.message);
if (failure.filename) {
return Ms.add(Ms.add(Ms.add(Ms.add(prefix, ' in '), failure.filename), ' line '), failure.lineno);
} else {
return prefix;
}
} else {
return Ms.add(afterAllMessagePrefix, failure.message);
}
}
addDeprecationWarnings(doneResult, this);
var warningBarClassName = 'jasmine-bar jasmine-warning';
var _DCAwT = Date.now();
for (i = 0; Ms.lt(i, this.deprecationWarnings.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _DCAwT), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var warning = this.deprecationWarnings[i];
alert.appendChild(createDom(this, 'span', {
className: warningBarClassName
}, Ms.add('DEPRECATION: ', warning)));
}
}
var results = find('.jasmine-results', this, 'jasmineDone');
results.appendChild(this.summary);
summaryList(this.stateBuilder.topResults, this.summary, this);
if (this.failures.length) {
alert.appendChild(createDom(this, 'span', {
className: 'jasmine-menu jasmine-bar jasmine-spec-list'
}, createDom(this, 'span', {}, 'Spec List | '), this.createAnchor({
className: 'jasmine-failures-menu',
href: '#'
}, 'Failures')));
alert.appendChild(createDom(this, 'span', {
className: 'jasmine-menu jasmine-bar jasmine-failure-list'
}, this.createAnchor({
className: 'jasmine-spec-list-menu',
href: '#'
}, 'Spec List'), createDom(this, 'span', {}, ' | Failures ')));
findAnchor('.jasmine-failures-menu', this).onclick = function() {
setMenuModeTo('jasmine-failure-list', _this);
return false;
};
findAnchor('.jasmine-spec-list-menu', this).onclick = function() {
setMenuModeTo('jasmine-spec-list', _this);
return false;
};
setMenuModeTo('jasmine-failure-list', this);
var failureNode = find('.jasmine-failures', this, 'jasmineDone');
var _ob7LK = Date.now();
for (i = 0; Ms.lt(i, this.failures.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _ob7LK), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
failureNode.appendChild(this.failures[i]);
}
}
}
};
HtmlReporter.prototype.createAnchor = function(attrs, text) {
var placeholder = {};
if (attrs.className) {
placeholder.className = attrs.className;
}
if (attrs.title) {
placeholder.title = attrs.title;
}
if (attrs.target) {
placeholder.target = attrs.target;
}
if (attrs.href) {
if (Ms.eq(attrs.target, '_blank')) {
placeholder.href = attrs.href;
}
}
if (Ms.eq(typeof text, 'string')) {
return createDom(this, 'a', placeholder, text);
} else {
return createDom(this, 'a', placeholder);
}
};
return HtmlReporter;
}();
exports_1('HtmlReporter', HtmlReporter);
}
};
});
System.register('./index.js', ['./Complex'], function(exports_1, context_1) {
'use strict';
var Complex_1, zero, one, i, result;
var __moduleName = context_1 && context_1.id;
return {
setters: [function(Complex_1_1) {
Complex_1 = Complex_1_1;
}],
execute: function() {
exports_1('zero', zero = Complex_1.complex(0, 0));
exports_1('one', one = Complex_1.complex(1, 0));
exports_1('i', i = Complex_1.complex(0, 1));
result = Ms.add(Ms.mul(5, one), Ms.mul(Ms.mul(2, one), i));
console.log('The answer to life, the universe, and everything is not '.concat(result.toString()));
}
};
});
System.register('./tests.js', [
'./HtmlReporter',
'./Complex.spec'
], function(exports_1, context_1) {
'use strict';
var HtmlReporter_1, Complex_spec_1, config, specifications;
var __moduleName = context_1 && context_1.id;
function getContainer() {
var element = document.body;
return element;
}
function onChangeOption(key, value) {
switch (key) {
case 'failFast': {
config.failFast = Ms.bang(config.failFast);
break;
}
case 'throwFailures': {
config.oneFailurePerSpec = Ms.bang(config.oneFailurePerSpec);
break;
}
case 'random': {
config.random = Ms.bang(config.random);
break;
}
case 'hideDisabled': {
config.hideDisabled = Ms.bang(config.hideDisabled);
break;
}
default: {
console.warn('navigateWithNewParam(key='.concat(key, ', value=').concat(JSON.stringify(value)));
}
}
runTests();
}
function addSpec(value) {
specifications.push(value);
return '';
}
function addSeed(_seed) {
return '';
}
function runTests() {
var jasmineCore = jasmineRequire.core(jasmineRequire);
jasmineRequire.html(jasmineCore);
var env = jasmineCore.getEnv();
var jasmineInterface = jasmineRequire.interface(jasmineCore, env);
extend(window, jasmineInterface);
var htmlReporter = new HtmlReporter_1.HtmlReporter({
env: env,
addToExistingQueryString: function(key, value) {
switch (key) {
case 'spec': {
return addSpec(value);
break;
}
case 'seed': {
return addSeed(parseInt(value, 10));
break;
}
default: {
throw new Error('Unknown key: '.concat(key));
}
}
},
navigateWithNewParam: onChangeOption,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
},
timer: new jasmine.Timer(),
filterSpecs: true
});
env.addReporter(jasmineInterface.jsApiReporter);
env.addReporter(htmlReporter);
env.configure(config);
htmlReporter.initialize();
describe('Complex', Complex_spec_1.complexSpec);
env.execute();
}
function extend(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
}
return {
setters: [
function(HtmlReporter_1_1) {
HtmlReporter_1 = HtmlReporter_1_1;
},
function(Complex_spec_1_1) {
Complex_spec_1 = Complex_spec_1_1;
}
],
execute: function() {
config = {
random: false,
failFast: false,
failSpecWithNoExpectations: false,
oneFailurePerSpec: false,
hideDisabled: false,
specFilter: void 0,
promise: void 0
};
specifications = [];
runTests();
}
};
});
</script>
<script>
System.defaultJSExtensions = true
System.import('./index.js').catch(function(e) {
console.error(e)
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.6.0/jasmine.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.6.0/jasmine.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.6.0/jasmine-html.min.js"></script>
<script src="/vendor/davinci-mathscript@1.3.5/davinci-mathscript.min.js"></script>
<script src="/assets/js/stemcstudio-systemjs@1.0.0/system.js"></script>
</head>
<body>
<script>
System.config({
"warnings": true,
"map": {
"jasmine": "https://cdn.jsdelivr.net/npm/jasmine@3.6.0/lib/jasmine.js"
}
});
</script>
<script>
System.register('./Complex.spec.js', ['./Complex'], function(exports_1, context_1) {
'use strict';
var Complex_1;
var __moduleName = context_1 && context_1.id;
function complexSpec() {
describe('constructor', function() {
var x = Math.random();
var y = Math.random();
var z = new Complex_1.Complex(x, y);
it('should preserve real argument', function() {
expect(z.real).toBe(x);
});
it('should preserve imag argument', function() {
expect(z.imag).toBe(y);
});
});
describe('Complex + Complex', function() {
var z1 = new Complex_1.Complex(2, 3);
var z2 = new Complex_1.Complex(5, 7);
var z = Ms.add(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.add(z1.real, z2.real));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(Ms.add(z1.imag, z2.imag));
});
});
describe('Complex + number', function() {
var z1 = new Complex_1.Complex(2, 3);
var z2 = 5;
var z = Ms.add(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.add(z1.real, z2));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(z1.imag);
});
});
describe('number + Complex', function() {
var z1 = 2;
var z2 = new Complex_1.Complex(5, 7);
var z = Ms.add(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.add(z1, z2.real));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(z2.imag);
});
});
describe('Complex * Complex', function() {
var z1 = new Complex_1.Complex(2, 3);
var z2 = new Complex_1.Complex(5, 7);
var z = Ms.mul(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.sub(Ms.mul(z1.real, z2.real), Ms.mul(z1.imag, z2.imag)));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(Ms.add(Ms.mul(z1.real, z2.imag), Ms.mul(z1.imag, z2.real)));
});
});
describe('Complex * number', function() {
var z1 = new Complex_1.Complex(2, 3);
var z2 = 5;
var z = Ms.mul(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.mul(z1.real, z2));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(Ms.mul(z1.imag, z2));
});
});
describe('number * Complex', function() {
var z1 = 2;
var z2 = new Complex_1.Complex(5, 7);
var z = Ms.mul(z1, z2);
it('should sum real argument', function() {
expect(z.real).toBe(Ms.mul(z1, z2.real));
});
it('should sum imag argument', function() {
expect(z.imag).toBe(Ms.mul(z1, z2.imag));
});
});
describe('-Complex', function() {
var z1 = new Complex_1.Complex(2, 3);
var z = Ms.neg(z1);
it('should negate real argument', function() {
expect(z.real).toBe(Ms.mul(z1.real, Ms.neg(1)));
});
it('should negate imag argument', function() {
expect(z.imag).toBe(Ms.mul(z1.imag, Ms.neg(1)));
});
});
}
exports_1('complexSpec', complexSpec);
return {
setters: [function(Complex_1_1) {
Complex_1 = Complex_1_1;
}],
execute: function() {}
};
});
System.register('./Complex.js', [], function(exports_1, context_1) {
'use strict';
var Complex;
var __moduleName = context_1 && context_1.id;
function complex(x, y) {
return new Complex(x, y);
}
exports_1('complex', complex);
return {
setters: [],
execute: function() {
Complex = function() {
function Complex(real, imag) {
this.real = real;
this.imag = imag;
}
Complex.prototype.__add__ = function(rhs) {
if (Ms.eq(typeof rhs, 'number')) {
return new Complex(Ms.add(this.real, rhs), this.imag);
} else if (rhs instanceof Complex) {
return new Complex(Ms.add(this.real, rhs.real), Ms.add(this.imag, rhs.imag));
} else {
return void 0;
}
};
Complex.prototype.__radd__ = function(lhs) {
if (Ms.eq(typeof lhs, 'number')) {
return new Complex(Ms.add(lhs, this.real), this.imag);
} else {
return void 0;
}
};
Complex.prototype.__mul__ = function(rhs) {
if (Ms.eq(typeof rhs, 'number')) {
return new Complex(Ms.mul(this.real, rhs), Ms.mul(this.imag, rhs));
} else if (rhs instanceof Complex) {
var x = Ms.sub(Ms.mul(this.real, rhs.real), Ms.mul(this.imag, rhs.imag));
var y = Ms.add(Ms.mul(this.real, rhs.imag), Ms.mul(this.imag, rhs.real));
return new Complex(x, y);
} else {
return void 0;
}
};
Complex.prototype.__rmul__ = function(lhs) {
if (Ms.eq(typeof lhs, 'number')) {
return new Complex(Ms.mul(lhs, this.real), Ms.mul(lhs, this.imag));
} else {
return void 0;
}
};
Complex.prototype.__neg__ = function() {
return new Complex(Ms.neg(this.real), Ms.neg(this.imag));
};
Complex.prototype.toString = function() {
return ''.concat(this.real, ' + ').concat(this.imag, ' * i');
};
return Complex;
}();
exports_1('Complex', Complex);
}
};
});
System.register('./HtmlReporter.js', [], function(exports_1, context_1) {
'use strict';
var ResultsNode, ResultsStateBuilder, HtmlReporter;
var __moduleName = context_1 && context_1.id;
function failureDom(result, reporter) {
var failure = createDom(reporter, 'div', {
className: 'jasmine-spec-detail jasmine-failed'
}, failureDescription(result, reporter.stateBuilder.currentParent, reporter), createDom(reporter, 'div', {
className: 'jasmine-messages'
}));
var messages = failure.childNodes[1];
var _xLORU = Date.now();
for (var _i = 0, _a = result.failedExpectations; Ms.lt(_i, _a.length); _i++) {
if (Ms.gt(Ms.sub(Date.now(), _xLORU), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var expectation = _a[_i];
messages.appendChild(createDom(reporter, 'div', {
className: 'jasmine-result-message'
}, expectation.message));
messages.appendChild(createDom(reporter, 'div', {
className: 'jasmine-stack-trace'
}, expectation.stack));
}
}
if (Ms.eq(result.failedExpectations.length, 0)) {
messages.appendChild(createDom(reporter, 'div', {
className: 'jasmine-result-message'
}, 'Spec has no expectations'));
}
return failure;
}
function summaryList(resultsTree, domParent, reporter) {
var specListNode;
var _lx9O7 = Date.now();
for (var i = 0; Ms.lt(i, resultsTree.children.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _lx9O7), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var resultNode = resultsTree.children[i];
if (reporter.filterSpecs && Ms.bang(hasActiveSpec(resultNode))) {
continue;
}
if (Ms.eq(resultNode.type, 'suite')) {
var result = resultNode.result;
var suiteListNode = createDom(reporter, 'ul', {
className: 'jasmine-suite',
id: Ms.add('suite-', result.id)
}, createDom(reporter, 'li', {
className: Ms.add('jasmine-suite-detail jasmine-', result.status)
}, reporter.createAnchor({
href: specHref(result, reporter)
}, result.description)));
summaryList(resultNode, suiteListNode, reporter);
domParent.appendChild(suiteListNode);
}
if (Ms.eq(resultNode.type, 'spec')) {
var result = resultNode.result;
if (Ms.ne(domParent.getAttribute('class'), 'jasmine-specs')) {
specListNode = createDom(reporter, 'ul', {
className: 'jasmine-specs'
});
domParent.appendChild(specListNode);
}
var specDescription = result.description;
if (noExpectations(result)) {
specDescription = Ms.add('SPEC HAS NO EXPECTATIONS ', specDescription);
}
if (Ms.eq(result.status, 'pending') && Ms.ne(result.pendingReason, '')) {
specDescription = Ms.add(Ms.add(specDescription, ' PENDING WITH MESSAGE: '), result.pendingReason);
}
specListNode.appendChild(createDom(reporter, 'li', {
className: Ms.add('jasmine-', result.status),
id: Ms.add('spec-', result.id)
}, reporter.createAnchor({
href: specHref(result, reporter)
}, specDescription)));
}
}
}
}
function optionsMenu(config, reporter) {
var optionsMenuDom = createDom(reporter, 'div', {
className: 'jasmine-run-options'
}, createDom(reporter, 'span', {
className: 'jasmine-trigger'
}, 'Options'), createDom(reporter, 'div', {
className: 'jasmine-payload'
}, createDom(reporter, 'div', {
className: 'jasmine-stop-on-failure'
}, createDom(reporter, 'input', {
className: 'jasmine-fail-fast',
id: 'jasmine-fail-fast',
type: 'checkbox'
}), createDom(reporter, 'label', {
className: 'jasmine-label',
for: 'jasmine-fail-fast'
}, 'stop execution on spec failure')), createDom(reporter, 'div', {
className: 'jasmine-throw-failures'
}, createDom(reporter, 'input', {
className: 'jasmine-throw',
id: 'jasmine-throw-failures',
type: 'checkbox'
}), createDom(reporter, 'label', {
className: 'jasmine-label',
for: 'jasmine-throw-failures'
}, 'stop spec on expectation failure')), createDom(reporter, 'div', {
className: 'jasmine-random-order'
}, createDom(reporter, 'input', {
className: 'jasmine-random',
id: 'jasmine-random-order',
type: 'checkbox'
}), createDom(reporter, 'label', {
className: 'jasmine-label',
for: 'jasmine-random-order'
}, 'run tests in random order')), createDom(reporter, 'div', {
className: 'jasmine-hide-disabled'
}, createDom(reporter, 'input', {
className: 'jasmine-disabled',
id: 'jasmine-hide-disabled',
type: 'checkbox'
}), createDom(reporter, 'label', {
className: 'jasmine-label',
for: 'jasmine-hide-disabled'
}, 'hide disabled tests'))));
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
failFastCheckbox.checked = config.failFast ? true : false;
failFastCheckbox.onclick = function() {
reporter.navigateWithNewParam('failFast', Ms.bang(config.failFast));
};
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
throwCheckbox.checked = config.oneFailurePerSpec ? true : false;
throwCheckbox.onclick = function() {
reporter.navigateWithNewParam('throwFailures', Ms.bang(config.oneFailurePerSpec));
};
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
randomCheckbox.checked = config.random ? true : false;
randomCheckbox.onclick = function() {
reporter.navigateWithNewParam('random', Ms.bang(config.random));
};
var hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled');
hideDisabled.checked = config.hideDisabled ? true : false;
hideDisabled.onclick = function() {
reporter.navigateWithNewParam('hideDisabled', Ms.bang(config.hideDisabled));
};
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger');
var optionsPayload = optionsMenuDom.querySelector('.jasmine-payload');
var isOpen = /\bjasmine-open\b/;
optionsTrigger.onclick = function() {
if (isOpen.test(optionsPayload.className)) {
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
} else {
optionsPayload.className += ' jasmine-open';
}
};
return optionsMenuDom;
}
function failureDescription(result, suite, reporter) {
var wrapper = createDom(reporter, 'div', {
className: 'jasmine-description'
}, reporter.createAnchor({
title: result.description,
href: specHref(result, reporter)
}, result.description));
var suiteLink;
var _aT1aZ = Date.now();
while (suite && suite.parent) {
if (Ms.gt(Ms.sub(Date.now(), _aT1aZ), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
wrapper.insertBefore(reporter.createTextNode(' > '), wrapper.firstChild);
suiteLink = reporter.createAnchor({
href: suiteHref(suite, reporter)
}, suite.result.description);
wrapper.insertBefore(suiteLink, wrapper.firstChild);
suite = suite.parent;
}
}
return wrapper;
}
function suiteHref(suite, reporter) {
var els = [];
var _Vpfcm = Date.now();
while (suite && suite.parent) {
if (Ms.gt(Ms.sub(Date.now(), _Vpfcm), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
els.unshift(suite.result.description);
suite = suite.parent;
}
}
return reporter.addToExistingQueryString('spec', els.join(' '));
}
function addDeprecationWarnings(result, reporter) {
if (result && result.deprecationWarnings) {
var _OqXnC = Date.now();
for (var i = 0; Ms.lt(i, result.deprecationWarnings.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _OqXnC), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var warning = result.deprecationWarnings[i].message;
reporter.deprecationWarnings.push(warning);
}
}
}
}
function findAnchor(selector, reporter) {
var element = find(selector, reporter, 'findAnchor');
if (element instanceof HTMLAnchorElement) {
return element;
} else {
throw new Error(''.concat(selector, ' is not an HTMLAnchorElement'));
}
}
function find(selector, reporter, _origin) {
var selectors = Ms.add('.jasmine_html-reporter ', selector);
var element = reporter.getContainer().querySelector(selectors);
if (element) {
return element;
} else {
throw new Error('Unable to find selectors '.concat(JSON.stringify(selectors)));
}
}
function clearPrior(reporter) {
try {
var oldReporter = find('', reporter, 'clearPrior');
reporter.getContainer().removeChild(oldReporter);
} catch (e) {}
}
exports_1('clearPrior', clearPrior);
function createDom(factory, type, attrs) {
var _children = [];
var _1H2dF = Date.now();
for (var _i = 3; Ms.lt(_i, arguments.length); _i++) {
if (Ms.gt(Ms.sub(Date.now(), _1H2dF), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
_children[_i - 3] = arguments[_i];
}
}
var el = factory.createElement(type);
var _01k9R = Date.now();
for (var i = 3; Ms.lt(i, arguments.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _01k9R), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var child = arguments[i];
if (Ms.eq(typeof child, 'string')) {
el.appendChild(factory.createTextNode(child));
} else {
if (child) {
el.appendChild(child);
}
}
}
}
for (var attr in attrs) {
if (Ms.eq(attr, 'className')) {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
}
function pluralize(singular, count) {
var word = Ms.eq(count, 1) ? singular : Ms.add(singular, 's');
return Ms.add(Ms.add(Ms.add('', count), ' '), word);
}
function specHref(result, reporter) {
return reporter.addToExistingQueryString('spec', result.fullName);
}
function seedHref(seed, reporter) {
return reporter.addToExistingQueryString('seed', seed);
}
function defaultQueryString(key, value) {
return Ms.add(Ms.add(Ms.add('?', key), '='), value);
}
function setMenuModeTo(mode, reporter) {
reporter.htmlReporterMain.setAttribute('class', Ms.add('jasmine_html-reporter ', mode));
}
function noExpectations(result) {
var allExpectations = Ms.add(result.failedExpectations.length, result.passedExpectations.length);
return Ms.eq(allExpectations, 0) && (Ms.eq(result.status, 'passed') || Ms.eq(result.status, 'failed'));
}
function hasActiveSpec(resultNode) {
if (Ms.eq(resultNode.type, 'spec')) {
var result = resultNode.result;
if (Ms.ne(result.status, 'excluded')) {
return true;
}
}
if (Ms.eq(resultNode.type, 'suite')) {
var j = resultNode.children.length;
var _6nUMa = Date.now();
for (var i = 0; Ms.lt(i, j); i++) {
if (Ms.gt(Ms.sub(Date.now(), _6nUMa), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
if (hasActiveSpec(resultNode.children[i])) {
return true;
}
}
}
}
return false;
}
return {
setters: [],
execute: function() {
ResultsNode = function() {
function ResultsNode(result, type, parent) {
this.result = result;
this.type = type;
this.parent = parent;
this.children = [];
}
ResultsNode.prototype.addChild = function(result, type) {
this.children.push(new ResultsNode(result, type, this));
};
ResultsNode.prototype.last = function() {
return this.children[this.children.length - 1];
};
ResultsNode.prototype.updateResult = function(result) {
this.result = result;
};
return ResultsNode;
}();
ResultsStateBuilder = function() {
function ResultsStateBuilder() {
this.topResults = new ResultsNode({
description: ''
}, 'suite', null);
this.currentParent = this.topResults;
this.specsExecuted = 0;
this.failureCount = 0;
this.pendingSpecCount = 0;
}
ResultsStateBuilder.prototype.suiteStarted = function(result) {
this.currentParent.addChild(result, 'suite');
this.currentParent = this.currentParent.last();
};
ResultsStateBuilder.prototype.suiteDone = function(result) {
this.currentParent.updateResult(result);
if (Ms.ne(this.currentParent, this.topResults)) {
this.currentParent = this.currentParent.parent;
}
if (Ms.eq(result.status, 'failed')) {
this.failureCount++;
}
};
ResultsStateBuilder.prototype.specStarted = function(_report) {};
ResultsStateBuilder.prototype.specDone = function(result) {
this.currentParent.addChild(result, 'spec');
if (Ms.ne(result.status, 'excluded')) {
this.specsExecuted++;
}
if (Ms.eq(result.status, 'failed')) {
this.failureCount++;
}
if (Ms.eq(result.status, 'pending')) {
this.pendingSpecCount++;
}
};
return ResultsStateBuilder;
}();
HtmlReporter = function() {
function HtmlReporter(options) {
this.failures = [];
this.deprecationWarnings = [];
this.stateBuilder = new ResultsStateBuilder();
this.config = function() {
return options.env && options.env.configuration() || {};
};
this.getContainer = options.getContainer;
this.createElement = options.createElement;
this.createTextNode = options.createTextNode;
this.navigateWithNewParam = options.navigateWithNewParam || function() {};
this.addToExistingQueryString = options.addToExistingQueryString || defaultQueryString;
this.filterSpecs = options.filterSpecs;
this.summary = createDom(this, 'div', {
className: 'jasmine-summary'
});
}
HtmlReporter.prototype.initialize = function() {
clearPrior(this);
this.htmlReporterMain = createDom(this, 'div', {
className: 'jasmine_html-reporter'
}, createDom(this, 'div', {
className: 'jasmine-banner'
}, this.createAnchor({
className: 'jasmine-title',
href: 'http://jasmine.github.io/',
target: '_blank'
}), createDom(this, 'span', {
className: 'jasmine-version'
}, jasmine.version)), createDom(this, 'ul', {
className: 'jasmine-symbol-summary'
}), createDom(this, 'div', {
className: 'jasmine-alert'
}), createDom(this, 'div', {
className: 'jasmine-results'
}, createDom(this, 'div', {
className: 'jasmine-failures'
})));
this.getContainer().appendChild(this.htmlReporterMain);
};
HtmlReporter.prototype.jasmineStarted = function(options) {
this.totalSpecsDefined = options.totalSpecsDefined || 0;
};
HtmlReporter.prototype.suiteStarted = function(result) {
this.stateBuilder.suiteStarted(result);
};
HtmlReporter.prototype.suiteDone = function(result) {
this.stateBuilder.suiteDone(result);
if (Ms.eq(result.status, 'failed')) {
this.failures.push(failureDom(result, this));
}
addDeprecationWarnings(result, this);
};
HtmlReporter.prototype.specStarted = function(result) {
this.stateBuilder.specStarted(result);
};
HtmlReporter.prototype.specDone = function(result) {
this.stateBuilder.specDone(result);
if (noExpectations(result)) {
var noSpecMsg = 'Spec "'.concat(result.fullName, '" has no expectations.');
if (Ms.eq(result.status, 'failed')) {
console.error(noSpecMsg);
} else {
console.warn(noSpecMsg);
}
}
if (Ms.bang(this.symbols)) {
this.symbols = find('.jasmine-symbol-summary', this, 'specDone');
}
this.symbols.appendChild(createDom(this, 'li', {
className: this.classNameFromSpecReport(result),
id: 'spec_'.concat(result.id),
title: result.fullName
}));
if (Ms.eq(result.status, 'failed')) {
this.failures.push(failureDom(result, this));
}
addDeprecationWarnings(result, this);
};
HtmlReporter.prototype.classNameFromSpecReport = function(report) {
return noExpectations(report) && Ms.eq(report.status, 'passed') ? 'jasmine-empty' : this.classNameFromStatus(report.status);
};
HtmlReporter.prototype.classNameFromStatus = function(status) {
switch (status) {
case 'excluded':
case 'passed': {
return this.config().hideDisabled ? 'jasmine-excluded-no-display' : 'jasmine-excluded';
}
case 'pending':
return 'jasmine-pending';
case 'failed':
return 'jasmine-failed';
default: {
throw new Error('classNameFromStatus(\''.concat(status, '\')'));
}
}
};
HtmlReporter.prototype.jasmineDone = function(doneResult) {
var _this = this;
var banner = find('.jasmine-banner', this, 'jasmineDone');
var alert = find('.jasmine-alert', this, 'jasmineDone');
var order = doneResult && doneResult.order;
var i;
alert.appendChild(createDom(this, 'span', {
className: 'jasmine-duration'
}, Ms.add(Ms.add('finished in ', Ms.div(doneResult.totalTime, 1000)), 's')));
banner.appendChild(optionsMenu(this.config(), this));
if (Ms.lt(this.stateBuilder.specsExecuted, this.totalSpecsDefined)) {
var skippedMessage = Ms.add(Ms.add(Ms.add(Ms.add('Ran ', this.stateBuilder.specsExecuted), ' of '), this.totalSpecsDefined), ' specs - run all');
var skippedLink = this.addToExistingQueryString('spec', '');
alert.appendChild(createDom(this, 'span', {
className: 'jasmine-bar jasmine-skipped'
}, this.createAnchor({
href: skippedLink,
title: 'Run all specs'
}, skippedMessage)));
}
var statusBarMessage = '';
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
var globalFailures = doneResult && doneResult.failedExpectations || [];
var failed = Ms.gt(Ms.add(this.stateBuilder.failureCount, globalFailures.length), 0);
if (Ms.gt(this.totalSpecsDefined, 0) || failed) {
statusBarMessage += Ms.add(Ms.add(pluralize('spec', this.stateBuilder.specsExecuted), ', '), pluralize('failure', this.stateBuilder.failureCount));
if (this.stateBuilder.pendingSpecCount) {
statusBarMessage += Ms.add(', ', pluralize('pending spec', this.stateBuilder.pendingSpecCount));
}
}
if (Ms.eq(doneResult.overallStatus, 'passed')) {
statusBarClassName += ' jasmine-passed ';
} else if (Ms.eq(doneResult.overallStatus, 'incomplete')) {
statusBarClassName += ' jasmine-incomplete ';
statusBarMessage = Ms.add(Ms.add(Ms.add('Incomplete: ', doneResult.incompleteReason), ', '), statusBarMessage);
} else {
statusBarClassName += ' jasmine-failed ';
}
if (order && order.random) {
var seedBar = createDom(this, 'span', {
className: 'jasmine-seed-bar'
}, ', randomized with seed ', this.createAnchor({
title: Ms.add('randomized with seed ', order.seed),
href: seedHref(order.seed, this)
}, order.seed));
alert.appendChild(createDom(this, 'span', {
className: statusBarClassName
}, statusBarMessage, seedBar));
} else {
alert.appendChild(createDom(this, 'span', {
className: statusBarClassName
}, statusBarMessage));
}
var errorBarClassName = 'jasmine-bar jasmine-errored';
var afterAllMessagePrefix = 'AfterAll ';
var _jeMSU = Date.now();
for (i = 0; Ms.lt(i, globalFailures.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _jeMSU), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
alert.appendChild(createDom(this, 'span', {
className: errorBarClassName
}, globalFailureMessage(globalFailures[i])));
}
}
function globalFailureMessage(failure) {
if (Ms.eq(failure.globalErrorType, 'load')) {
var prefix = Ms.add('Error during loading: ', failure.message);
if (failure.filename) {
return Ms.add(Ms.add(Ms.add(Ms.add(prefix, ' in '), failure.filename), ' line '), failure.lineno);
} else {
return prefix;
}
} else {
return Ms.add(afterAllMessagePrefix, failure.message);
}
}
addDeprecationWarnings(doneResult, this);
var warningBarClassName = 'jasmine-bar jasmine-warning';
var _UdJWH = Date.now();
for (i = 0; Ms.lt(i, this.deprecationWarnings.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _UdJWH), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
var warning = this.deprecationWarnings[i];
alert.appendChild(createDom(this, 'span', {
className: warningBarClassName
}, Ms.add('DEPRECATION: ', warning)));
}
}
var results = find('.jasmine-results', this, 'jasmineDone');
results.appendChild(this.summary);
summaryList(this.stateBuilder.topResults, this.summary, this);
if (this.failures.length) {
alert.appendChild(createDom(this, 'span', {
className: 'jasmine-menu jasmine-bar jasmine-spec-list'
}, createDom(this, 'span', {}, 'Spec List | '), this.createAnchor({
className: 'jasmine-failures-menu',
href: '#'
}, 'Failures')));
alert.appendChild(createDom(this, 'span', {
className: 'jasmine-menu jasmine-bar jasmine-failure-list'
}, this.createAnchor({
className: 'jasmine-spec-list-menu',
href: '#'
}, 'Spec List'), createDom(this, 'span', {}, ' | Failures ')));
findAnchor('.jasmine-failures-menu', this).onclick = function() {
setMenuModeTo('jasmine-failure-list', _this);
return false;
};
findAnchor('.jasmine-spec-list-menu', this).onclick = function() {
setMenuModeTo('jasmine-spec-list', _this);
return false;
};
setMenuModeTo('jasmine-failure-list', this);
var failureNode = find('.jasmine-failures', this, 'jasmineDone');
var _hemKA = Date.now();
for (i = 0; Ms.lt(i, this.failures.length); i++) {
if (Ms.gt(Ms.sub(Date.now(), _hemKA), 1000)) {
throw new Error('Infinite loop suspected after 1000 milliseconds.');
} {
failureNode.appendChild(this.failures[i]);
}
}
}
};
HtmlReporter.prototype.createAnchor = function(attrs, text) {
var placeholder = {};
if (attrs.className) {
placeholder.className = attrs.className;
}
if (attrs.title) {
placeholder.title = attrs.title;
}
if (attrs.target) {
placeholder.target = attrs.target;
}
if (attrs.href) {
if (Ms.eq(attrs.target, '_blank')) {
placeholder.href = attrs.href;
}
}
if (Ms.eq(typeof text, 'string')) {
return createDom(this, 'a', placeholder, text);
} else {
return createDom(this, 'a', placeholder);
}
};
return HtmlReporter;
}();
exports_1('HtmlReporter', HtmlReporter);
}
};
});
System.register('./index.js', ['./Complex'], function(exports_1, context_1) {
'use strict';
var Complex_1, zero, one, i, result;
var __moduleName = context_1 && context_1.id;
return {
setters: [function(Complex_1_1) {
Complex_1 = Complex_1_1;
}],
execute: function() {
exports_1('zero', zero = Complex_1.complex(0, 0));
exports_1('one', one = Complex_1.complex(1, 0));
exports_1('i', i = Complex_1.complex(0, 1));
result = Ms.add(Ms.mul(5, one), Ms.mul(Ms.mul(2, one), i));
console.log('The answer to life, the universe, and everything is not '.concat(result.toString()));
}
};
});
System.register('./tests.js', [
'./HtmlReporter',
'./Complex.spec'
], function(exports_1, context_1) {
'use strict';
var HtmlReporter_1, Complex_spec_1, config, specifications;
var __moduleName = context_1 && context_1.id;
function getContainer() {
var element = document.body;
return element;
}
function onChangeOption(key, value) {
switch (key) {
case 'failFast': {
config.failFast = Ms.bang(config.failFast);
break;
}
case 'throwFailures': {
config.oneFailurePerSpec = Ms.bang(config.oneFailurePerSpec);
break;
}
case 'random': {
config.random = Ms.bang(config.random);
break;
}
case 'hideDisabled': {
config.hideDisabled = Ms.bang(config.hideDisabled);
break;
}
default: {
console.warn('navigateWithNewParam(key='.concat(key, ', value=').concat(JSON.stringify(value)));
}
}
runTests();
}
function addSpec(value) {
specifications.push(value);
return '';
}
function addSeed(_seed) {
return '';
}
function runTests() {
var jasmineCore = jasmineRequire.core(jasmineRequire);
jasmineRequire.html(jasmineCore);
var env = jasmineCore.getEnv();
var jasmineInterface = jasmineRequire.interface(jasmineCore, env);
extend(window, jasmineInterface);
var htmlReporter = new HtmlReporter_1.HtmlReporter({
env: env,
addToExistingQueryString: function(key, value) {
switch (key) {
case 'spec': {
return addSpec(value);
break;
}
case 'seed': {
return addSeed(parseInt(value, 10));
break;
}
default: {
throw new Error('Unknown key: '.concat(key));
}
}
},
navigateWithNewParam: onChangeOption,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
},
timer: new jasmine.Timer(),
filterSpecs: true
});
env.addReporter(jasmineInterface.jsApiReporter);
env.addReporter(htmlReporter);
env.configure(config);
htmlReporter.initialize();
describe('Complex', Complex_spec_1.complexSpec);
env.execute();
}
function extend(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
}
return {
setters: [
function(HtmlReporter_1_1) {
HtmlReporter_1 = HtmlReporter_1_1;
},
function(Complex_spec_1_1) {
Complex_spec_1 = Complex_spec_1_1;
}
],
execute: function() {
config = {
random: false,
failFast: false,
failSpecWithNoExpectations: false,
oneFailurePerSpec: false,
hideDisabled: false,
specFilter: void 0,
promise: void 0
};
specifications = [];
runTests();
}
};
});
</script>
<script>
System.defaultJSExtensions = true
System.import('./tests.js').catch(function(e) {
console.error(e)
})
</script>
</body>
</html>
// type ResultStatus = 'excluded' | 'disabled' | 'failed' | 'pending' | 'finished'
type ResultsNodeResult = jasmine.SuiteStartedReport | jasmine.SuiteDoneReport | jasmine.SpecDoneReport | { description: string }
class ResultsNode {
type: 'spec' | 'suite'
result: ResultsNodeResult
children: ResultsNode[]
parent: ResultsNode | null
constructor(result: ResultsNodeResult, type: 'spec' | 'suite', parent: ResultsNode | null) {
this.result = result
this.type = type
this.parent = parent
this.children = []
}
addChild(result: ResultsNodeResult, type: 'spec' | 'suite'): void {
this.children.push(new ResultsNode(result, type, this))
}
last(): ResultsNode {
return this.children[this.children.length - 1]
}
updateResult(result: ResultsNodeResult): void {
this.result = result
}
}
class ResultsStateBuilder {
topResults: ResultsNode
currentParent: ResultsNode
specsExecuted: number
failureCount: number
pendingSpecCount: number
constructor() {
this.topResults = new ResultsNode({ description: "" }, 'suite', null)
this.currentParent = this.topResults
this.specsExecuted = 0
this.failureCount = 0
this.pendingSpecCount = 0
}
suiteStarted(result: jasmine.SuiteStartedReport): void {
this.currentParent.addChild(result, 'suite')
this.currentParent = this.currentParent.last()
}
suiteDone(result: jasmine.SuiteDoneReport): void {
this.currentParent.updateResult(result)
if (this.currentParent !== this.topResults) {
this.currentParent = this.currentParent.parent as ResultsNode
}
if (result.status === 'failed') {
this.failureCount++
}
}
specStarted(_report: jasmine.SpecStartedReport): void {
// Do nothing
}
specDone(result: jasmine.SpecDoneReport) {
this.currentParent.addChild(result, 'spec')
if (result.status !== 'excluded') {
this.specsExecuted++
}
if (result.status === 'failed') {
this.failureCount++
}
if (result.status === 'pending') {
this.pendingSpecCount++
}
}
}
/**
* Customized HtmlReporter so that we can create placeholder hyperlinks.
*/
export class HtmlReporter implements jasmine.Reporter {
config: () => jasmine.EnvConfiguration
failures: HTMLElement[] = []
getContainer: () => HTMLElement
createElement: (type: 'div' | 'a' | 'ul' | 'span') => HTMLElement
createTextNode: (text: string) => Text
navigateWithNewParam: any
/**
* Use to generate href attributes for HTMLAnchorElements.
*/
addToExistingQueryString: (key: 'seed' | 'spec', value: string) => string
filterSpecs: any
symbols: Element
deprecationWarnings: string[] = []
summary: HTMLElement
htmlReporterMain: HTMLElement
totalSpecsDefined: number
stateBuilder = new ResultsStateBuilder()
constructor(options: jasmine.HtmlReporterOptions) {
this.config = function() {
return (options.env && options.env.configuration()) || {}
}
this.getContainer = options.getContainer
this.createElement = options.createElement
this.createTextNode = options.createTextNode
this.navigateWithNewParam = options.navigateWithNewParam || function() { }
this.addToExistingQueryString = options.addToExistingQueryString || defaultQueryString
this.filterSpecs = options.filterSpecs
this.summary = createDom(this, 'div', { className: 'jasmine-summary' })
}
initialize() {
clearPrior(this)
this.htmlReporterMain = createDom(this,
'div',
{ className: 'jasmine_html-reporter' },
createDom(this,
'div',
{ className: 'jasmine-banner' },
this.createAnchor({ className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank' }),
createDom(this, 'span', { className: 'jasmine-version' }, jasmine.version)
),
createDom(this, 'ul', { className: 'jasmine-symbol-summary' }),
createDom(this, 'div', { className: 'jasmine-alert' }),
createDom(this, 'div', { className: 'jasmine-results' }, createDom(this, 'div', { className: 'jasmine-failures' }))
)
this.getContainer().appendChild(this.htmlReporterMain)
}
jasmineStarted(options: jasmine.JasmineStartedReport) {
this.totalSpecsDefined = options.totalSpecsDefined || 0
}
suiteStarted(result: jasmine.SuiteStartedReport) {
this.stateBuilder.suiteStarted(result)
}
suiteDone(result: jasmine.SuiteDoneReport) {
this.stateBuilder.suiteDone(result)
if (result.status === 'failed') {
this.failures.push(failureDom(result, this))
}
addDeprecationWarnings(result, this)
}
specStarted(result: jasmine.SpecStartedReport) {
this.stateBuilder.specStarted(result)
}
specDone(result: jasmine.SpecDoneReport) {
this.stateBuilder.specDone(result)
if (noExpectations(result)) {
const noSpecMsg = `Spec "${result.fullName}" has no expectations.`
if (result.status === 'failed') {
console.error(noSpecMsg)
} else {
console.warn(noSpecMsg)
}
}
if (!this.symbols) {
this.symbols = find('.jasmine-symbol-summary', this, 'specDone')
}
this.symbols.appendChild(
createDom(this, 'li', {
className: this.classNameFromSpecReport(result),
id: `spec_${result.id}`,
title: result.fullName
})
)
if (result.status === 'failed') {
this.failures.push(failureDom(result, this))
}
addDeprecationWarnings(result, this)
}
classNameFromSpecReport(report: jasmine.SpecDoneReport) {
return noExpectations(report) && (report.status === 'passed') ? 'jasmine-empty' : this.classNameFromStatus(report.status)
}
classNameFromStatus(status: 'excluded' | 'passed' | 'failed' | 'disabled' | 'pending'): 'jasmine-excluded-no-display' | 'jasmine-excluded' | 'jasmine-pending' | 'jasmine-failed' | 'jasmine-' {
switch (status) {
case 'excluded':
case 'passed': {
return this.config().hideDisabled ? 'jasmine-excluded-no-display' : 'jasmine-excluded'
}
case 'pending': return 'jasmine-pending'
case 'failed': return 'jasmine-failed'
default: {
throw new Error(`classNameFromStatus('${status}')`)
}
}
}
jasmineDone(doneResult: jasmine.JasmineDoneReport) {
const banner = find('.jasmine-banner', this, 'jasmineDone')
const alert = find('.jasmine-alert', this, 'jasmineDone')
const order = doneResult && doneResult.order
let i: number
alert.appendChild(
createDom(this, 'span', { className: 'jasmine-duration' }, 'finished in ' + doneResult.totalTime / 1000 + 's')
)
banner.appendChild(optionsMenu(this.config(), this))
if (this.stateBuilder.specsExecuted < this.totalSpecsDefined) {
const skippedMessage =
'Ran ' +
this.stateBuilder.specsExecuted +
' of ' +
this.totalSpecsDefined +
' specs - run all'
const skippedLink = this.addToExistingQueryString('spec', '')
alert.appendChild(
createDom(this,
'span',
{ className: 'jasmine-bar jasmine-skipped' },
this.createAnchor({ href: skippedLink, title: 'Run all specs' }, skippedMessage)
)
)
}
let statusBarMessage = ''
let statusBarClassName = 'jasmine-overall-result jasmine-bar '
const globalFailures = (doneResult && doneResult.failedExpectations) || []
const failed = this.stateBuilder.failureCount + globalFailures.length > 0
if (this.totalSpecsDefined > 0 || failed) {
statusBarMessage += pluralize('spec', this.stateBuilder.specsExecuted) + ', ' + pluralize('failure', this.stateBuilder.failureCount)
if (this.stateBuilder.pendingSpecCount) {
statusBarMessage += ', ' + pluralize('pending spec', this.stateBuilder.pendingSpecCount)
}
}
if (doneResult.overallStatus === 'passed') {
statusBarClassName += ' jasmine-passed '
} else if (doneResult.overallStatus === 'incomplete') {
statusBarClassName += ' jasmine-incomplete '
statusBarMessage =
'Incomplete: ' +
doneResult.incompleteReason +
', ' +
statusBarMessage
} else {
statusBarClassName += ' jasmine-failed '
}
if (order && order.random) {
const seedBar = createDom(this,
'span',
{ className: 'jasmine-seed-bar' },
', randomized with seed ',
this.createAnchor({ title: 'randomized with seed ' + order.seed, href: seedHref(order.seed, this) }, order.seed)
)
alert.appendChild(createDom(this, 'span', { className: statusBarClassName }, statusBarMessage, seedBar))
}
else {
alert.appendChild(createDom(this, 'span', { className: statusBarClassName }, statusBarMessage))
}
const errorBarClassName = 'jasmine-bar jasmine-errored'
const afterAllMessagePrefix = 'AfterAll '
for (i = 0; i < globalFailures.length; i++) {
alert.appendChild(
createDom(this,
'span',
{ className: errorBarClassName },
globalFailureMessage(globalFailures[i])
)
)
}
function globalFailureMessage(failure: { globalErrorType: 'load'; message: string; filename: string; lineno: number }) {
if (failure.globalErrorType === 'load') {
const prefix = 'Error during loading: ' + failure.message
if (failure.filename) {
return (
prefix + ' in ' + failure.filename + ' line ' + failure.lineno
)
} else {
return prefix
}
} else {
return afterAllMessagePrefix + failure.message
}
}
addDeprecationWarnings(doneResult, this)
const warningBarClassName = 'jasmine-bar jasmine-warning'
for (i = 0; i < this.deprecationWarnings.length; i++) {
const warning = this.deprecationWarnings[i]
alert.appendChild(
createDom(this,
'span',
{ className: warningBarClassName },
'DEPRECATION: ' + warning
)
)
}
const results = find('.jasmine-results', this, 'jasmineDone')
results.appendChild(this.summary)
summaryList(this.stateBuilder.topResults, this.summary, this)
if (this.failures.length) {
alert.appendChild(
createDom(this,
'span',
{ className: 'jasmine-menu jasmine-bar jasmine-spec-list' },
createDom(this, 'span', {}, 'Spec List | '),
this.createAnchor({ className: 'jasmine-failures-menu', href: '#' }, 'Failures')
)
)
alert.appendChild(
createDom(this,
'span',
{ className: 'jasmine-menu jasmine-bar jasmine-failure-list' },
this.createAnchor({ className: 'jasmine-spec-list-menu', href: '#' }, 'Spec List'),
createDom(this, 'span', {}, ' | Failures ')
)
)
findAnchor('.jasmine-failures-menu', this).onclick = () => {
setMenuModeTo('jasmine-failure-list', this)
return false
}
findAnchor('.jasmine-spec-list-menu', this).onclick = () => {
setMenuModeTo('jasmine-spec-list', this)
return false
}
setMenuModeTo('jasmine-failure-list', this)
const failureNode = find('.jasmine-failures', this, 'jasmineDone')
for (i = 0; i < this.failures.length; i++) {
failureNode.appendChild(this.failures[i])
}
}
}
/**
* Intercept all calls to create HTMLAnchorElement(s) so that we can create
* placeholder hyperlinks that don't navigate anywhere.
*/
public createAnchor(attrs: { className?: string; href?: string; title?: string; target?: '_blank' }, text?: string): HTMLAnchorElement {
const placeholder: { className?: string; href?: string; title?: string; target?: string } = {}
if (attrs.className) {
placeholder.className = attrs.className
}
if (attrs.title) {
placeholder.title = attrs.title
}
if (attrs.target) {
placeholder.target = attrs.target
}
if (attrs.href) {
if (attrs.target === '_blank') {
placeholder.href = attrs.href
}
}
if (typeof text === 'string') {
return createDom(this, 'a', placeholder, text) as HTMLAnchorElement
}
else {
return createDom(this, 'a', placeholder) as HTMLAnchorElement
}
}
}
function failureDom(result: jasmine.SuiteDoneReport | jasmine.SpecDoneReport, reporter: HtmlReporter) {
const failure = createDom(reporter,
'div',
{ className: 'jasmine-spec-detail jasmine-failed' },
failureDescription(result, reporter.stateBuilder.currentParent, reporter),
createDom(reporter, 'div', { className: 'jasmine-messages' })
)
const messages = failure.childNodes[1]
for (const expectation of result.failedExpectations) {
messages.appendChild(createDom(reporter, 'div', { className: 'jasmine-result-message' }, expectation.message))
messages.appendChild(createDom(reporter, 'div', { className: 'jasmine-stack-trace' }, expectation.stack)
)
}
if (result.failedExpectations.length === 0) {
messages.appendChild(createDom(reporter, 'div', { className: 'jasmine-result-message' }, 'Spec has no expectations'))
}
return failure
}
function summaryList(resultsTree: ResultsNode, domParent: HTMLElement, reporter: HtmlReporter) {
let specListNode: any
for (let i = 0; i < resultsTree.children.length; i++) {
const resultNode = resultsTree.children[i]
if (reporter.filterSpecs && !hasActiveSpec(resultNode)) {
continue
}
if (resultNode.type === 'suite') {
const result = resultNode.result as jasmine.SuiteDoneReport
const suiteListNode = createDom(reporter,
'ul',
{ className: 'jasmine-suite', id: 'suite-' + result.id },
createDom(reporter, 'li', { className: 'jasmine-suite-detail jasmine-' + result.status },
reporter.createAnchor({ href: specHref(result, reporter) }, result.description)
)
)
summaryList(resultNode, suiteListNode, reporter)
domParent.appendChild(suiteListNode)
}
if (resultNode.type === 'spec') {
const result = resultNode.result as jasmine.SpecDoneReport
if (domParent.getAttribute('class') !== 'jasmine-specs') {
specListNode = createDom(reporter, 'ul', { className: 'jasmine-specs' })
domParent.appendChild(specListNode)
}
let specDescription = result.description
if (noExpectations(result)) {
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription
}
if (result.status === 'pending' && result.pendingReason !== '') {
specDescription =
specDescription +
' PENDING WITH MESSAGE: ' +
result.pendingReason
}
specListNode.appendChild(
createDom(reporter,
'li',
{
className: 'jasmine-' + result.status,
id: 'spec-' + result.id
},
reporter.createAnchor({ href: specHref(result, reporter) }, specDescription)
)
)
}
}
}
function optionsMenu(config: jasmine.EnvConfiguration, reporter: HtmlReporter) {
const optionsMenuDom = createDom(reporter,
'div',
{ className: 'jasmine-run-options' },
createDom(reporter, 'span', { className: 'jasmine-trigger' }, 'Options'),
createDom(reporter,
'div',
{ className: 'jasmine-payload' },
createDom(reporter,
'div',
{ className: 'jasmine-stop-on-failure' },
createDom(reporter, 'input', {
className: 'jasmine-fail-fast',
id: 'jasmine-fail-fast',
type: 'checkbox'
}),
createDom(reporter,
'label',
{ className: 'jasmine-label', for: 'jasmine-fail-fast' },
'stop execution on spec failure'
)
),
createDom(reporter,
'div',
{ className: 'jasmine-throw-failures' },
createDom(reporter, 'input', {
className: 'jasmine-throw',
id: 'jasmine-throw-failures',
type: 'checkbox'
}),
createDom(reporter,
'label',
{ className: 'jasmine-label', for: 'jasmine-throw-failures' },
'stop spec on expectation failure'
)
),
createDom(reporter,
'div',
{ className: 'jasmine-random-order' },
createDom(reporter, 'input', {
className: 'jasmine-random',
id: 'jasmine-random-order',
type: 'checkbox'
}),
createDom(reporter,
'label',
{ className: 'jasmine-label', for: 'jasmine-random-order' },
'run tests in random order'
)
),
createDom(reporter,
'div',
{ className: 'jasmine-hide-disabled' },
createDom(reporter, 'input', {
className: 'jasmine-disabled',
id: 'jasmine-hide-disabled',
type: 'checkbox'
}),
createDom(reporter,
'label',
{ className: 'jasmine-label', for: 'jasmine-hide-disabled' },
'hide disabled tests'
)
)
)
)
const failFastCheckbox: HTMLInputElement = optionsMenuDom.querySelector('#jasmine-fail-fast') as HTMLInputElement
failFastCheckbox.checked = config.failFast ? true : false
failFastCheckbox.onclick = function() {
reporter.navigateWithNewParam('failFast', !config.failFast)
}
const throwCheckbox: HTMLInputElement = optionsMenuDom.querySelector('#jasmine-throw-failures') as HTMLInputElement
throwCheckbox.checked = config.oneFailurePerSpec ? true : false
throwCheckbox.onclick = function() {
reporter.navigateWithNewParam('throwFailures', !config.oneFailurePerSpec)
}
const randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order') as HTMLInputElement
randomCheckbox.checked = config.random ? true : false
randomCheckbox.onclick = function() {
reporter.navigateWithNewParam('random', !config.random)
}
const hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled') as HTMLInputElement
hideDisabled.checked = config.hideDisabled ? true : false
hideDisabled.onclick = function() {
reporter.navigateWithNewParam('hideDisabled', !config.hideDisabled)
}
const optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger') as HTMLButtonElement
const optionsPayload = optionsMenuDom.querySelector('.jasmine-payload') as HTMLElement
const isOpen = /\bjasmine-open\b/
optionsTrigger.onclick = function() {
if (isOpen.test(optionsPayload.className)) {
optionsPayload.className = optionsPayload.className.replace(
isOpen,
''
)
} else {
optionsPayload.className += ' jasmine-open'
}
}
return optionsMenuDom
}
function failureDescription(result: jasmine.SuiteDoneReport | jasmine.SpecDoneReport, suite: ResultsNode, reporter: HtmlReporter) {
const wrapper = createDom(reporter,
'div',
{ className: 'jasmine-description' },
reporter.createAnchor({ title: result.description, href: specHref(result, reporter) }, result.description)
)
let suiteLink
while (suite && suite.parent) {
wrapper.insertBefore(reporter.createTextNode(' > '), wrapper.firstChild)
suiteLink = reporter.createAnchor({ href: suiteHref(suite, reporter) }, suite.result.description)
wrapper.insertBefore(suiteLink, wrapper.firstChild)
suite = suite.parent
}
return wrapper
}
function suiteHref(suite: { parent: any; result: any }, reporter: HtmlReporter) {
// console.lg(`suiteHref()`)
const els = []
while (suite && suite.parent) {
els.unshift(suite.result.description)
suite = suite.parent
}
return reporter.addToExistingQueryString('spec', els.join(' '))
}
function addDeprecationWarnings(result: jasmine.SpecDoneReport | jasmine.SuiteDoneReport | jasmine.JasmineDoneReport, reporter: HtmlReporter) {
if (result && result.deprecationWarnings) {
for (let i = 0; i < result.deprecationWarnings.length; i++) {
const warning = result.deprecationWarnings[i].message
// if (!j$.util.arrayContains(warning)) {
reporter.deprecationWarnings.push(warning)
// }
}
}
}
function findAnchor(selector: string, reporter: HtmlReporter): HTMLAnchorElement {
const element = find(selector, reporter, 'findAnchor')
if (element instanceof HTMLAnchorElement) {
return element
}
else {
throw new Error(`${selector} is not an HTMLAnchorElement`)
}
}
function find(selector: string, reporter: HtmlReporter, _origin: 'findAnchor' | 'clearPrior' | 'specDone' | 'jasmineDone'): Element {
// console.lg(`find(selector=${JSON.stringify(selector)}, origin=${origin})`)
const selectors = '.jasmine_html-reporter ' + selector
const element = reporter.getContainer().querySelector(selectors)
if (element) {
return element
}
else {
throw new Error(`Unable to find selectors ${JSON.stringify(selectors)}`)
}
}
export function clearPrior(reporter: HtmlReporter) {
try {
const oldReporter = find('', reporter, 'clearPrior')
reporter.getContainer().removeChild(oldReporter)
}
catch (e) {
// We end up here if the oldReporter does not exist.
// TODO: Perhaps we also need a find that does not throw?
}
}
function createDom(factory: jasmine.HtmlReporterFactory, type: 'div' | 'a' | 'ul' | 'li' | 'span' | 'label' | 'input', attrs: {}, ..._children: (string | HTMLElement)[]) {
const el = factory.createElement(type)
for (let i = 3; i < arguments.length; i++) {
const child = arguments[i]
if (typeof child === 'string') {
el.appendChild(factory.createTextNode(child))
} else {
if (child) {
el.appendChild(child)
}
}
}
for (const attr in attrs) {
if (attr === 'className') {
el[attr] = attrs[attr]
} else {
el.setAttribute(attr, attrs[attr])
}
}
return el
}
function pluralize(singular: string, count: number): string {
const word = count === 1 ? singular : singular + 's'
return '' + count + ' ' + word
}
function specHref(result: { fullName: string }, reporter: HtmlReporter) {
return reporter.addToExistingQueryString('spec', result.fullName)
}
function seedHref(seed: string, reporter: HtmlReporter) {
return reporter.addToExistingQueryString('seed', seed)
}
function defaultQueryString(key: 'spec' | 'seed', value: string): string {
return '?' + key + '=' + value
}
function setMenuModeTo(mode: string, reporter: HtmlReporter) {
reporter.htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode)
}
function noExpectations(result: jasmine.SpecDoneReport) {
const allExpectations =
result.failedExpectations.length + result.passedExpectations.length
return (allExpectations === 0 && (result.status === 'passed' || result.status === 'failed'))
}
function hasActiveSpec(resultNode: ResultsNode): boolean {
if (resultNode.type === 'spec') {
const result = resultNode.result as (jasmine.SpecDoneReport)
if (result.status !== 'excluded') {
return true
}
}
if (resultNode.type === 'suite') {
const j = resultNode.children.length
for (let i = 0; i < j; i++) {
if (hasActiveSpec(resultNode.children[i])) {
return true
}
}
}
return false
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
Nothing to see here, take a look at the tests
</body>
</html>
import { complex } from './Complex'
/**
* Life, the universe, and everything.
*/
export const zero = complex(0, 0)
export const one = complex(1, 0)
export const i = complex(0, 1)
const result = 5 * one + 2 * one * i
console.log(`The answer to life, the universe, and everything is not ${result.toString()}`)
{
"description": "Operator Overloading",
"dependencies": {
"jasmine": "3.6.0"
},
"name": "operator-overloading-complex-numbers",
"version": "1.0.0",
"author": "David Geo Holmes",
"keywords": [
"Operator",
"Overloading",
"dunder",
"operators",
"unary",
"binary"
]
}
{
"hideConfigFiles": false,
"hideReferenceFiles": false,
"linting": false,
"noLoopCheck": false,
"operatorOverloading": true,
"overrides": [],
"references": {},
"showGeneratedFiles": false
}
body {
background-color: white;
}
{
"warnings": true,
"map": {
"jasmine": "https://cdn.jsdelivr.net/npm/jasmine@3.6.0/package.json"
}
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
import { HtmlReporter } from './HtmlReporter'
import { complexSpec } from './Complex.spec'
/**
* These configuration parameters determine how the tests are executed.
*/
const config: jasmine.EnvConfiguration = {
random: false,
failFast: false,
failSpecWithNoExpectations: false,
oneFailurePerSpec: false,
hideDisabled: false,
specFilter: void 0,
promise: void 0
}
const specifications: string[] = []
function getContainer(): HTMLElement {
const element = document.body
return element
}
function onChangeOption(key: 'failFast' | 'throwFailures' | 'random' | 'hideDisabled', value: string): void {
switch (key) {
case 'failFast': {
config.failFast = !config.failFast
break
}
case 'throwFailures': {
config.oneFailurePerSpec = !config.oneFailurePerSpec
break
}
case 'random': {
config.random = !config.random
break
}
case 'hideDisabled': {
config.hideDisabled = !config.hideDisabled
break
}
default: {
console.warn(`navigateWithNewParam(key=${key}, value=${JSON.stringify(value)}`)
}
}
runTests()
}
/**
* Generate an href for an HTMLAnchorElement.
*/
function addSpec(value: string): string {
specifications.push(value)
return ''
}
/**
* Generate an href for an HTMLAnchorElement.
*/
function addSeed(_seed: number): string {
// console.info(`onSeed(seed=${seed})`)
// config.seed = value
return ''
}
function runTests() {
const jasmineCore: jasmine.Jasmine = jasmineRequire.core(jasmineRequire)
// We shouldn't need to do this...
jasmineRequire.html(jasmineCore)
const env = jasmineCore.getEnv()
// Build the collection of functions that we use in our specs and put them in the global namespace.
const jasmineInterface = jasmineRequire.interface(jasmineCore, env)
/**
* Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly.
* For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
*/
extend(window, jasmineInterface)
// const catchingExceptions = queryString.getParam("catch")
// env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions)
const htmlReporter = new /*jasmine.*/HtmlReporter({
env: env,
addToExistingQueryString: function(key: 'seed' | 'spec', value: string): string {
switch (key) {
case 'spec': {
return addSpec(value)
break
}
case 'seed': {
return addSeed(parseInt(value, 10))
break
}
default: {
throw new Error(`Unknown key: ${key}`)
}
}
},
navigateWithNewParam: onChangeOption,
getContainer,
createElement: function(): HTMLElement {
return document.createElement.apply(document, arguments)
},
createTextNode: function(): Text {
return document.createTextNode.apply(document, arguments)
},
timer: new jasmine.Timer(),
filterSpecs: true // Will only be true if query string contains 'spec'.
})
env.addReporter(jasmineInterface.jsApiReporter)
env.addReporter(htmlReporter)
env.configure(config)
htmlReporter.initialize()
// Declare your specification definitions here.
describe("Complex", complexSpec)
env.execute()
}
runTests()
/*
* Helper function for extending the properties on objects.
*/
function extend<T>(destination: T, source: any): T {
for (const property in source) {
if (source.hasOwnProperty(property)) {
(<any> destination)[property] = source[property]
}
}
return destination
}
{
"allowJs": true,
"checkJs": true,
"declaration": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"jsx": "react",
"module": "system",
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"preserveConstEnums": true,
"removeComments": false,
"skipLibCheck": true,
"sourceMap": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5",
"traceResolution": true
}
{
"rules": {
"array-type": [
true,
"array"
],
"curly": false,
"comment-format": [
true,
"check-space"
],
"eofline": true,
"forin": true,
"jsdoc-format": true,
"new-parens": true,
"no-conditional-assignment": false,
"no-consecutive-blank-lines": true,
"no-construct": true,
"no-for-in-array": true,
"no-inferrable-types": [
true
],
"no-magic-numbers": false,
"no-shadowed-variable": true,
"no-string-throw": true,
"no-trailing-whitespace": [
true,
"ignore-jsdoc"
],
"no-var-keyword": true,
"one-variable-per-declaration": [
true,
"ignore-for-loop"
],
"prefer-const": true,
"prefer-for-of": true,
"prefer-function-over-method": false,
"prefer-method-signature": true,
"radix": true,
"semicolon": [
true,
"never"
],
"trailing-comma": [
true,
{
"multiline": "never",
"singleline": "never"
}
],
"triple-equals": true,
"use-isnan": true
}
}
{
"warnings": true,
"map": {
"jasmine": "https://cdn.jsdelivr.net/npm/@types/jasmine@3.6.0/package.json"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment