diff --git a/package-lock.json b/package-lock.json index da74be50..9323e914 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "chs-js-lib", - "version": "0.3.1", + "version": "0.3.2", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.3.1", + "version": "0.3.2", "license": "ISC", "dependencies": { "http-server": "^14.1.0", diff --git a/package.json b/package.json index 3464d4f3..411bbb78 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chs-js-lib", - "version": "0.3.1", + "version": "0.3.2", "description": "JavaScript graphics library used in CodeHS's platform.", "main": "dist/chs.cjs", "module": "dist/chs.mjs", diff --git a/src/console/index.js b/src/console/index.js index a4a32972..a6864d62 100644 --- a/src/console/index.js +++ b/src/console/index.js @@ -160,7 +160,7 @@ class Console { * @private */ readNumber(str, parseFn, errorMsgType, asynchronous) { - const DEFAULT = 0; // If we get into an infinite recursion, return DEFAULT. + const DEFAULT = Symbol(); // If we get into an infinite recursion, return DEFAULT. const MAX_RECURSION_DEPTH = 100; // a special indicator that th program should be exiting const ABORT = Symbol('ABORT'); @@ -215,7 +215,17 @@ class Console { } } }; - return attemptInput(promptString, 0, asynchronous); + const result = attemptInput(promptString, 0, asynchronous); + if (result === DEFAULT) { + return 0; + } + if (result === null) { + return null; + } + // success + this.print(str); + this.println(result); + return result; } /** diff --git a/src/graphics/circle.js b/src/graphics/circle.js index 6e4bb2b9..2de78115 100644 --- a/src/graphics/circle.js +++ b/src/graphics/circle.js @@ -51,6 +51,12 @@ class Circle extends Thing { context.translate(-this.radius, -this.radius); }); } + /** + * Describes the circle for use with screen readers. + */ + describe() { + return super.describe() + ` Radius: ${this.radius}.`; + } /** * Gets the radius of the circle diff --git a/src/graphics/rectangle.js b/src/graphics/rectangle.js index 6dc37f50..fd284280 100644 --- a/src/graphics/rectangle.js +++ b/src/graphics/rectangle.js @@ -51,6 +51,13 @@ class Rectangle extends Thing { }); } + /** + * Describes the rectangle for use with screen readers. + */ + describe() { + return super.describe() + ` Width: ${this.width}. Height: ${this.height}.`; + } + /** * Sets the size of the Rectangle. * diff --git a/src/graphics/text.js b/src/graphics/text.js index 42ad1d45..37b00355 100644 --- a/src/graphics/text.js +++ b/src/graphics/text.js @@ -80,7 +80,7 @@ class Text extends Thing { } describe() { - return super.describe() + this.label; + return super.describe() + ' ' + this.label + ` in font ${this.font}.`; } /** diff --git a/src/graphics/thing.js b/src/graphics/thing.js index 3acf4ef5..cdda9270 100644 --- a/src/graphics/thing.js +++ b/src/graphics/thing.js @@ -607,7 +607,8 @@ class Thing { * to print a text descriptino of the Thing. */ describe() { - return `A ${this.type} at ${this.x}, ${this.y}. Colored: ${this.color}.`; + const color = this.color.startsWith('#') ? this.color.toUpperCase() : this.color; + return `A ${this.type} at ${this.x}, ${this.y}. Colored: ${color}.`; } /** diff --git a/test/circle.test.js b/test/circle.test.js index 204c7c70..b74c96c3 100644 --- a/test/circle.test.js +++ b/test/circle.test.js @@ -228,4 +228,14 @@ describe('Circle', () => { }); }); }); + describe('.describe', () => { + it('Describes the Circle correctly', () => { + const c = new Circle(125); + c.setPosition(100, 25); + expect(c.describe()).toEqual('A Circle at 100, 25. Colored: #000000. Radius: 125.'); + c.setRadius(45); + c.setColor('green'); + expect(c.describe()).toEqual('A Circle at 100, 25. Colored: green. Radius: 45.'); + }); + }); }); diff --git a/test/console.test.js b/test/console.test.js index d2801fe5..1c99bf7c 100644 --- a/test/console.test.js +++ b/test/console.test.js @@ -133,6 +133,13 @@ describe('Console', () => { expect(promptSpy).toHaveBeenCalledOnceWith('give me a line!'); expect(windowPromptSpy).toHaveBeenCalledOnceWith('modified prompt'); }); + it('Prints a parsed result', () => { + const promptSpy = spyOn(window, 'prompt').and.returnValue('hiya'); + const outputSpy = jasmine.createSpy(); + const c = new Console({ output: outputSpy }); + c.readLine('give me a line!'); + expect(outputSpy.calls.allArgs()).toEqual([['give me a line!'], ['hiya', '\n']]); + }); }); describe('readFloat', () => { it('Errors for >1 argument', () => { @@ -211,6 +218,20 @@ describe('Console', () => { expect(promptSpy).toHaveBeenCalledOnceWith('give me an int!'); expect(windowPromptSpy).toHaveBeenCalledOnceWith('modified prompt'); }); + it('Prints a parsed result', () => { + const promptSpy = spyOn(window, 'prompt').and.returnValue(1); + const outputSpy = jasmine.createSpy(); + const c = new Console({ output: outputSpy }); + c.readInt('give me an int!'); + expect(outputSpy.calls.allArgs()).toEqual([['give me an int!'], [1, '\n']]); + }); + it('Doesnt print a default value', () => { + const promptSpy = spyOn(window, 'prompt').and.returnValue(null); + const outputSpy = jasmine.createSpy(); + const c = new Console({ output: outputSpy }); + c.readInt('give me an int!'); + expect(outputSpy.calls.allArgs()).toEqual([]); + }); }); describe('readBoolean', () => { it('Errors for >1 argument', () => { diff --git a/test/rectangle.test.js b/test/rectangle.test.js index 038cf011..d2ab47e6 100644 --- a/test/rectangle.test.js +++ b/test/rectangle.test.js @@ -101,4 +101,12 @@ describe('Rectangle', () => { ); }); }); + describe('.describe', () => { + it('Describes the Rectangle correctly', () => { + const r = new Rectangle(45, 10); + expect(r.describe()).toEqual( + 'A Rectangle at 0, 0. Colored: #000000. Width: 45. Height: 10.' + ); + }); + }); }); diff --git a/test/text.test.js b/test/text.test.js index 783794c6..8b018cc8 100644 --- a/test/text.test.js +++ b/test/text.test.js @@ -123,4 +123,18 @@ describe('Text', () => { expect(t.containsPoint(5, 5)).toBeTrue(); }); }); + describe('.describe', () => { + it('Describes the Text correctly', () => { + const t = new Text('Hello World!'); + expect(t.describe()).toEqual( + 'A Text at 0, 0. Colored: #000000. Hello World! in font 20pt Arial.' + ); + t.setFont('10pt Helvetica'); + t.setPosition(50, 177); + t.setColor('#4cc9f0'); + expect(t.describe()).toEqual( + 'A Text at 50, 177. Colored: #4CC9F0. Hello World! in font 10pt Helvetica.' + ); + }); + }); }); diff --git a/test/thing.test.js b/test/thing.test.js index 64947ef1..82b4a53c 100644 --- a/test/thing.test.js +++ b/test/thing.test.js @@ -129,4 +129,16 @@ describe('Thing', () => { expect(t.getType()).toEqual('newType'); }); }); + describe('.describe', () => { + it('Describes the thing correctly', () => { + const t = new Thing(); + expect(t.describe()).toEqual('A Thing at 0, 0. Colored: #000000.'); + t.setColor('#bad345'); + expect(t.describe()).toEqual('A Thing at 0, 0. Colored: #BAD345.'); + t.setColor('white'); + expect(t.describe()).toEqual('A Thing at 0, 0. Colored: white.'); + t.setPosition(30, 45); + expect(t.describe()).toEqual('A Thing at 30, 45. Colored: white.'); + }); + }); });