mirror of
				https://github.com/JuanCanham/HackMyResume.git
				synced 2025-10-31 13:17:26 +00:00 
			
		
		
		
	Improve conversions and tests.
This commit is contained in:
		| @@ -55,10 +55,8 @@ FRESH to JSON Resume conversion routiens. | ||||
|         writing: writing( src.publications, true), | ||||
|         recognition: recognition( src.awards, true, foreign ), | ||||
|         social: social( src.basics.profiles, true ), | ||||
|  | ||||
|  | ||||
|         interests: src.interests, | ||||
|         references: src.references, | ||||
|         testimonials: references( src.references, true ), | ||||
|         languages: src.languages, | ||||
|         disposition: src.disposition // <--> round-trip | ||||
|       }; | ||||
| @@ -101,7 +99,7 @@ FRESH to JSON Resume conversion routiens. | ||||
|         awards: recognition( src.recognition, false, foreign ), | ||||
|         publications: writing( src.writing, false ), | ||||
|         interests: src.interests, | ||||
|         references: src.references, | ||||
|         references: references( src.testimonials, false ), | ||||
|         samples: foreign ? src.samples : undefined, | ||||
|         disposition: foreign ? src.disposition : undefined, | ||||
|         languages: src.languages | ||||
| @@ -275,6 +273,27 @@ FRESH to JSON Resume conversion routiens. | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function references( obj, direction ) { | ||||
|     if( direction ) { | ||||
|       return obj && obj.length && obj.map(function(ref){ | ||||
|         return { | ||||
|           name: ref.name, | ||||
|           flavor: 'professional', | ||||
|           quote: ref.reference, | ||||
|           private: false | ||||
|         }; | ||||
|       }); | ||||
|     } | ||||
|     else { | ||||
|       return obj && obj.length && obj.map(function(ref){ | ||||
|         return { | ||||
|           name: ref.name, | ||||
|           reference: ref.quote | ||||
|         }; | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function writing( obj, direction ) { | ||||
|     if( direction ) { | ||||
|       return obj.map(function( pub ) { | ||||
| @@ -292,7 +311,7 @@ FRESH to JSON Resume conversion routiens. | ||||
|       return obj && obj.length ? obj.map(function(pub){ | ||||
|         return { | ||||
|           name: pub.title, | ||||
|           publisher: pub.publisher, | ||||
|           publisher: pub.publisher && pub.publisher.name ? pub.publisher.name : pub.publisher, | ||||
|           releaseDate: pub.date, | ||||
|           website: pub.url, | ||||
|           summary: pub.summary | ||||
|   | ||||
| @@ -66,7 +66,10 @@ FluentDate/*.prototype*/.fmt = function( dt ) { | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     if( dt.isValid && dt.isValid() ) | ||||
|     if( !dt ) { | ||||
|       return moment(); | ||||
|     } | ||||
|     else if( dt.isValid && dt.isValid() ) | ||||
|       return dt; | ||||
|     throw 'Unknown date object encountered.'; | ||||
|   } | ||||
|   | ||||
| @@ -12,7 +12,8 @@ Definition of the FRESHResume class. | ||||
|     , PATH = require('path') | ||||
|     , moment = require('moment') | ||||
|     , MD = require('marked') | ||||
|     , CONVERTER = require('./convert'); | ||||
|     , CONVERTER = require('./convert') | ||||
|     , JRSResume = require('./jrs-resume'); | ||||
|  | ||||
|   /** | ||||
|   A FRESH-style resume in JSON or YAML. | ||||
| @@ -46,13 +47,14 @@ Definition of the FRESHResume class. | ||||
|   Save the sheet to disk in a specific format, either FRESH or JSON Resume. | ||||
|   */ | ||||
|   FreshResume.prototype.saveAs = function( filename, format ) { | ||||
|     this.imp.fileName = filename || this.imp.fileName; | ||||
|  | ||||
|     if( format !== 'JRS' ) { | ||||
|       this.imp.fileName = filename || this.imp.fileName; | ||||
|       FS.writeFileSync( this.imp.fileName, this.stringify(), 'utf8' ); | ||||
|     } | ||||
|     else { | ||||
|       var newRep = CONVERTER.toJRS( this ); | ||||
|       FS.writeFileSync( this.imp.fileName, FreshResume.stringify( newRep ), 'utf8' ); | ||||
|       FS.writeFileSync( filename, JRSResume.stringify( newRep ), 'utf8' ); | ||||
|     } | ||||
|     return this; | ||||
|   }; | ||||
|   | ||||
| @@ -30,17 +30,22 @@ Definition of the JRSResume class. | ||||
|   consistent format. Then sort each section by startDate descending. | ||||
|   */ | ||||
|   JRSResume.prototype.open = function( file, title ) { | ||||
|     this.imp = { fileName: file }; | ||||
|     this.imp.raw = FS.readFileSync( file, 'utf8' ); | ||||
|     return this.parse( this.imp.raw, title ); | ||||
|     //this.imp = { fileName: file }; <-- schema violation, tuck it into .basics instead | ||||
|     this.basics = { | ||||
|       imp: { | ||||
|         fileName: file, | ||||
|         raw: FS.readFileSync( file, 'utf8' ) | ||||
|       } | ||||
|     }; | ||||
|     return this.parse( this.basics.imp.raw, title ); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|   Save the sheet to disk (for environments that have disk access). | ||||
|   */ | ||||
|   JRSResume.prototype.save = function( filename ) { | ||||
|     this.imp.fileName = filename || this.imp.fileName; | ||||
|     FS.writeFileSync( this.imp.fileName, this.stringify(), 'utf8' ); | ||||
|     this.basics.imp.fileName = filename || this.basics.imp.fileName; | ||||
|     FS.writeFileSync( this.basics.imp.fileName, this.stringify( this ), 'utf8' ); | ||||
|     return this; | ||||
|   }; | ||||
|  | ||||
| @@ -48,7 +53,7 @@ Definition of the JRSResume class. | ||||
|   Convert this object to a JSON string, sanitizing meta-properties along the | ||||
|   way. Don't override .toString(). | ||||
|   */ | ||||
|   JRSResume.prototype.stringify = function() { | ||||
|   JRSResume.stringify = function( obj ) { | ||||
|     function replacer( key,value ) { // Exclude these keys from stringification | ||||
|       return _.some(['imp', 'warnings', 'computed', 'filt', 'ctrl', 'index', | ||||
|         'safeStartDate', 'safeEndDate', 'safeDate', 'safeReleaseDate', 'result', | ||||
| @@ -56,7 +61,11 @@ Definition of the JRSResume class. | ||||
|         function( val ) { return key.trim() === val; } | ||||
|       ) ? undefined : value; | ||||
|     } | ||||
|     return JSON.stringify( this, replacer, 2 ); | ||||
|     return JSON.stringify( obj, replacer, 2 ); | ||||
|   }; | ||||
|  | ||||
|   JRSResume.prototype.stringify = function() { | ||||
|     return JRSResume.stringify( this ); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
| @@ -67,16 +76,17 @@ Definition of the JRSResume class. | ||||
|   JRSResume.prototype.parse = function( stringData, opts ) { | ||||
|     opts = opts || { }; | ||||
|     var rep = JSON.parse( stringData ); | ||||
|  | ||||
|     extend( true, this, rep ); | ||||
|     // Set up metadata | ||||
|     if( opts.imp === undefined || opts.imp ) { | ||||
|       this.imp = this.imp || { }; | ||||
|       this.imp.title = (opts.title || this.imp.title) || this.basics.name; | ||||
|       this.basics.imp = this.basics.imp || { }; | ||||
|       this.basics.imp.title = (opts.title || this.basics.imp.title) || this.basics.name; | ||||
|     } | ||||
|     // Parse dates, sort dates, and calculate computed values | ||||
|     (opts.date === undefined || opts.date) && _parseDates.call( this ); | ||||
|     (opts.sort === undefined || opts.sort) && this.sort(); | ||||
|     (opts.compute === undefined || opts.compute) && (this.computed = { | ||||
|     (opts.compute === undefined || opts.compute) && (this.basics.computed = { | ||||
|       numYears: this.duration(), | ||||
|       keywords: this.keywords() | ||||
|     }); | ||||
| @@ -111,7 +121,7 @@ Definition of the JRSResume class. | ||||
|   JRSResume.prototype.clear = function( clearMeta ) { | ||||
|     clearMeta = ((clearMeta === undefined) && true) || clearMeta; | ||||
|     clearMeta && (delete this.imp); | ||||
|     delete this.computed; // Don't use Object.keys() here | ||||
|     delete this.basics.computed; // Don't use Object.keys() here | ||||
|     delete this.work; | ||||
|     delete this.volunteer; | ||||
|     delete this.education; | ||||
| @@ -169,8 +179,15 @@ Definition of the JRSResume class. | ||||
|     var schema = FS.readFileSync( PATH.join( __dirname, 'resume.json' ), 'utf8' ); | ||||
|     var schemaObj = JSON.parse( schema ); | ||||
|     var validator = require('is-my-json-valid'); | ||||
|     var validate = validator( schemaObj ); | ||||
|     return validate( this ); | ||||
|     var validate = validator( schemaObj, { // Note [1] | ||||
|       formats: { date: /^\d{4}(?:-(?:0[0-9]{1}|1[0-2]{1})(?:-[0-9]{2})?)?$/ } | ||||
|     }); | ||||
|     var ret = validate( this ); | ||||
|     if( !ret ) { | ||||
|       this.basics.imp = this.basics.imp || { }; | ||||
|       this.basics.imp.validationErrors = validate.errors; | ||||
|     } | ||||
|     return ret; | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|   | ||||
							
								
								
									
										224
									
								
								tests/resumes/jrs/jane-doe.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								tests/resumes/jrs/jane-doe.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| { | ||||
|   "basics": { | ||||
|     "name": "Jane Doe", | ||||
|     "label": "Senior Developer / Code Ninja", | ||||
|     "summary": "**Full-stack software developer with 6+ years industry experience** specializing in scalable cloud architectures for this, that, and the other. A native of southern CA, Jane enjoys hiking, mystery novels, and the company of Rufus, her two-year-old beagle.", | ||||
|     "website": "http://jane-doe.me", | ||||
|     "phone": "1-650-999-7777", | ||||
|     "email": "jdoe@onecoolstartup.io", | ||||
|     "picture": "jane_doe.png", | ||||
|     "location": { | ||||
|       "address": "Jane Doe\n123 Somewhere Rd.\nMountain View, CA 94035", | ||||
|       "postalCode": "94035", | ||||
|       "city": "Mountain View", | ||||
|       "countryCode": "US", | ||||
|       "region": "CA" | ||||
|     }, | ||||
|     "profiles": [ | ||||
|       { | ||||
|         "network": "GitHub", | ||||
|         "username": "jane-doe-was-here", | ||||
|         "url": "https://github.com/jane-doe-was-here" | ||||
|       }, | ||||
|       { | ||||
|         "network": "Twitter", | ||||
|         "username": "jane-doe-was-here", | ||||
|         "url": "https://twitter.com/jane-doe-was-here" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "work": [ | ||||
|     { | ||||
|       "company": "One Cool Startup", | ||||
|       "website": "https://onecool.io/does-not-exist", | ||||
|       "position": "Head Code Ninja", | ||||
|       "startDate": "2013-09", | ||||
|       "summary": "Development team manager for OneCoolApp and OneCoolWebsite, a free social network tiddlywink generator and lifestyle portal with over 200,000 users.", | ||||
|       "highlights": [ | ||||
|         "Managed a 5-person development team", | ||||
|         "Accomplishment 2", | ||||
|         "Etc." | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "company": "Veridian Dynamics", | ||||
|       "website": "https://en.wikipedia.org/wiki/Better_Off_Ted#Plot", | ||||
|       "position": "Principal Developer", | ||||
|       "startDate": "2011-07", | ||||
|       "endDate": "2013-08", | ||||
|       "summary": "Developer on numerous projects culminating in technical lead role for the [Jabberwocky project](http://betteroffted.wikia.com/wiki/Jabberwocky) and promotion to principal developer.", | ||||
|       "highlights": [ | ||||
|         "Managed a 5-person development team", | ||||
|         "Accomplishment 2", | ||||
|         "Etc." | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "company": "Stark Industries", | ||||
|       "position": "IT Administrator", | ||||
|       "startDate": "2008-10", | ||||
|       "endDate": "2011-06", | ||||
|       "summary": "Junior programmer with heavy code responsibilities. Promoted to intermediate role after 6 months.", | ||||
|       "highlights": [ | ||||
|         "Promoted to intermediate developer after 6 months", | ||||
|         "Accomplishment 2", | ||||
|         "Etc." | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "company": "Dunder Mifflin", | ||||
|       "position": "Intern", | ||||
|       "startDate": "2008-06", | ||||
|       "endDate": "2008-09", | ||||
|       "summary": "Performed IT administration and deployments for Dunder Mifflin.", | ||||
|       "highlights": [ | ||||
|         "Supervised roll-out of Dunder Mifflin Infinity website.", | ||||
|         "Performed mission-critical system backups and ", | ||||
|         "Etc." | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   "education": [ | ||||
|     { | ||||
|       "institution": "Cornell University", | ||||
|       "gpa": "3.5", | ||||
|       "courses": [ | ||||
|         "Course 1", | ||||
|         "Course 2", | ||||
|         "Course 2" | ||||
|       ], | ||||
|       "startDate": "2005-09", | ||||
|       "endDate": "2008-05" | ||||
|     }, | ||||
|     { | ||||
|       "institution": "Medfield College", | ||||
|       "gpa": "3.2", | ||||
|       "courses": [ | ||||
|         "Course 1", | ||||
|         "Course 2", | ||||
|         "Course 2" | ||||
|       ], | ||||
|       "startDate": "2003-09", | ||||
|       "endDate": "2005-06" | ||||
|     } | ||||
|   ], | ||||
|   "skills": [ | ||||
|     { | ||||
|       "name": "Programming", | ||||
|       "keywords": [ | ||||
|         "C++", | ||||
|         "Ruby", | ||||
|         "Xcode" | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "name": "Project Management", | ||||
|       "keywords": [ | ||||
|         "Agile" | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   "volunteer": [ | ||||
|     { | ||||
|       "organization": "Technology for Tots", | ||||
|       "position": "Technical Consultant", | ||||
|       "startDate": "2003-11", | ||||
|       "endDate": "2005-06", | ||||
|       "website": "http://technology-for-tots.org", | ||||
|       "summary": "Summary of this volunteer stint.", | ||||
|       "highlights": [ | ||||
|         "Accomplishment 1", | ||||
|         "Accomplishment 2", | ||||
|         "etc" | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "organization": "US Army Reserves", | ||||
|       "position": "NCO", | ||||
|       "startDate": "1999-11", | ||||
|       "endDate": "2003-06", | ||||
|       "website": "http://www.usar.army.mil/", | ||||
|       "summary": "Summary of this military stint.", | ||||
|       "highlights": [ | ||||
|         "Accomplishment 1", | ||||
|         "Accomplishment 2", | ||||
|         "etc" | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   "awards": [ | ||||
|     { | ||||
|       "title": "Honorable Mention", | ||||
|       "date": "2012", | ||||
|       "awarder": "Google" | ||||
|     }, | ||||
|     { | ||||
|       "title": "Summa cum laude", | ||||
|       "date": "2012", | ||||
|       "awarder": "Cornell University" | ||||
|     } | ||||
|   ], | ||||
|   "publications": [ | ||||
|     { | ||||
|       "name": "Building User Interfaces with Electron and Atom", | ||||
|       "publisher": "Code Project", | ||||
|       "releaseDate": "2011", | ||||
|       "website": "http://codeproject.com/build-ui-electron-atom.aspx" | ||||
|     }, | ||||
|     { | ||||
|       "name": "Jane Doe Unplugged", | ||||
|       "publisher": "self", | ||||
|       "releaseDate": "2011", | ||||
|       "website": "http://jane-doe.me" | ||||
|     }, | ||||
|     { | ||||
|       "name": "Teach Yourself GORFF in 21 Days", | ||||
|       "publisher": "Amazon", | ||||
|       "releaseDate": "2008", | ||||
|       "website": "http://url.to.publication.com/blah", | ||||
|       "summary": "A primer on the programming language of GORFF, whose for loops are coterminous with all of time and space." | ||||
|     } | ||||
|   ], | ||||
|   "interests": [ | ||||
|     { | ||||
|       "name": "reading", | ||||
|       "summary": "Jane is a fan of mystery novels and courtroom dramas including Agatha Christie and John Grisham.", | ||||
|       "keywords": [ | ||||
|         "mystery", | ||||
|         "Agatha Christie", | ||||
|         "John Grisham" | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "name": "hiking", | ||||
|       "summary": "Jane enjoys hiking, light mountain climbing, and has four summits under her belt!" | ||||
|     }, | ||||
|     { | ||||
|       "name": "yoga" | ||||
|     } | ||||
|   ], | ||||
|   "references": [ | ||||
|     { | ||||
|       "name": "John Davidson", | ||||
|       "reference": "Jane is awesome! I'd hire her again in a heartbeat." | ||||
|     }, | ||||
|     { | ||||
|       "name": "Elias Fullstacker", | ||||
|       "reference": "I worked with Jane on Jabberwocky and can vouch for her awesome technical capabilities and attention to detail. Insta-hire." | ||||
|     }, | ||||
|     { | ||||
|       "name": "Dana Nevins", | ||||
|       "reference": "I've known Jane personally and professionally for almost ten years. She is one in a million." | ||||
|     } | ||||
|   ], | ||||
|   "languages": [ | ||||
|     { | ||||
|       "language": "English", | ||||
|       "level": "Native" | ||||
|     }, | ||||
|     { | ||||
|       "language": "Spanish", | ||||
|       "level": "Moderate" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| @@ -17,7 +17,7 @@ describe('FRESH/JRS converter', function () { | ||||
|  | ||||
| 	  it('should round-trip from JRS to FRESH to JRS without modifying or losing data', function () { | ||||
|  | ||||
|       var fileA = path.join( __dirname, 'jrs-exemplar/richard-hendriks.json' ); | ||||
|       var fileA = path.join( __dirname, 'resumes/jrs/richard-hendriks.json' ); | ||||
|       var fileB = path.join( __dirname, 'sandbox/richard-hendriks.json' ); | ||||
|  | ||||
|       _sheet = new FRESHResume().open( fileA ); | ||||
|   | ||||
| @@ -9,13 +9,14 @@ var chai = require('chai') | ||||
|  | ||||
| chai.config.includeStack = false; | ||||
|  | ||||
| describe('fullstack.json (JRS)', function () { | ||||
| describe('jane-doe.json (JRS)', function () { | ||||
|  | ||||
|     var _sheet; | ||||
|  | ||||
| 	  it('should open without throwing an exception', function () { | ||||
|       function tryOpen() { | ||||
|         _sheet = new JRSResume().open( 'node_modules/resample/fullstack/in/resume.json' ); | ||||
|         _sheet = new JRSResume().open( | ||||
|           path.join( __dirname, 'resumes/jrs/jane-doe.json' ) ); | ||||
|       } | ||||
|       tryOpen.should.not.Throw(); | ||||
|     }); | ||||
| @@ -32,28 +33,29 @@ describe('fullstack.json (JRS)', function () { | ||||
|       ).to.equal( true ); | ||||
|     }); | ||||
|  | ||||
|     it('should have a work duration of 11 years', function() { | ||||
|       _sheet.computed.numYears.should.equal( 11 ); | ||||
|     it('should have a work duration of 7 years', function() { | ||||
|       _sheet.basics.computed.numYears.should.equal( 7 ); | ||||
|     }); | ||||
|  | ||||
|     it('should save without throwing an exception', function(){ | ||||
|       function trySave() { | ||||
|         _sheet.save( 'tests/sandbox/fullstack.json' ); | ||||
|         _sheet.save( 'tests/sandbox/jane-doe.json' ); | ||||
|       } | ||||
|       trySave.should.not.Throw(); | ||||
|     }); | ||||
|  | ||||
|     it('should not be modified after saving', function() { | ||||
|       var savedSheet = new JRSResume().open( 'tests/sandbox/fullstack.json' ); | ||||
|       var savedSheet = new JRSResume().open( 'tests/sandbox/jane-doe.json' ); | ||||
|       _sheet.stringify().should.equal( savedSheet.stringify() ) | ||||
|     }); | ||||
|  | ||||
|     it('should validate against the JSON Resume schema', function() { | ||||
|       var schemaJson = require('../src/core/resume.json'); | ||||
|       var validate = validator( schemaJson, { verbose: true } ); | ||||
|       var result = validate( JSON.parse( _sheet.imp.raw ) ); | ||||
|       var result = _sheet.isValid(); | ||||
|       // var schemaJson = require('../src/core/resume.json'); | ||||
|       // var validate = validator( schemaJson, { verbose: true } ); | ||||
|       // var result = validate( JSON.parse( _sheet.imp.raw ) ); | ||||
|       result || console.log("\n\nOops, resume didn't validate. " + | ||||
|        "Validation errors:\n\n", validate.errors, "\n\n"); | ||||
|        "Validation errors:\n\n", _sheet.basics.imp.validationErrors, "\n\n"); | ||||
|       result.should.equal( true ); | ||||
|     }); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user