UNPKG

mailjs

Version:

JavaScript HTML and text email renderer/formatter.

628 lines (566 loc) 15.7 kB
var mailjs = require( '../mail' ), chai = require( 'chai' ), expect = chai.expect; describe( 'attribute parser', function() { it( 'should parse all three quote styles', function() { expect( mailjs.parseAttrs( " foo='faz' bar=\"baz\" car=caz" ) ).to.eql( { foo: 'faz', bar: 'baz', car: 'caz' } ); }); it( 'should parse empty strings', function() { expect( mailjs.parseAttrs( ' ' ) ).to.eql( {} ); }); }); describe( 'element parser', function() { it( 'should parse simple tags', function() { expect( mailjs.parseElement( '[a]' ) ).to.eql( { el: '[a]', tag: 'a', attrs: {} } ); }); it( 'should parse all three quote styles', function() { expect( mailjs.parseElement( "[a foo='faz' bar=\"baz\" car=caz]" ) ).to.eql( { el: "[a foo='faz' bar=\"baz\" car=caz]", tag: 'a', attrs: { foo: 'faz', bar: 'baz', car: 'caz' } } ); }); it( 'should deal with quoted brackets', function() { expect( mailjs.parseElement( "[div tag='[div style=\"color:#000;\"]']" ) ).to.eql( { el: "[div tag='[div style=\"color:#000;\"]']", tag: 'div', attrs: { tag: '[div style="color:#000;"]' } } ); }); it( 'should throw on empty elements', function() { expect( function() { mailjs.parseElement( '' ) }).to.throw(); expect( function() { mailjs.parseElement( '[]' ) }).to.throw(); }); it( 'should throw on invalid elements', function() { expect( function() { return mailjs.parseElement( '[a style]' ) }).to.throw(); }); it( 'should throw on incomplete elements', function() { expect( function() { return mailjs.parseElement( '[' ) }).to.throw(); expect( function() { return mailjs.parseElement( '[a style' ) }).to.throw(); }); it( 'should support self-closing elements', function() { expect( mailjs.parseElement( '[a style="display:block;"/]' ) ).to.eql( { el: '[a style="display:block;"/]', tag: 'a', attrs: { style: 'display:block;' }, selfClose: true } ); }); it( 'should support closing elements', function() { expect( mailjs.parseElement( '[/a]' ) ).to.eql( { el: '[/a]', tag: 'a', attrs: {}, close: true } ); }); it( 'should throw on elements that are closed and self-closed', function() { expect( function() { return mailjs.parseElement( '[/a/]' ) }).to.throw( /closed and self-closed/ ); }); it( 'should throw on closed elements that have attributes', function() { expect( function() { return mailjs.parseElement( '[/a style="color:#000;"]' ) }).to.throw( /Closed elements should not contain attributes/ ); }); it( 'should parse tag-value elements', function() { expect( mailjs.parseElement( '[email="support@apple.com"]' ) ).to.eql( { el: '[email="support@apple.com"]', tag: 'email', attrs: { email: 'support@apple.com' } } ); expect( mailjs.parseElement( '[pixels=300px]' ) ).to.eql( { el: '[pixels=300px]', tag: 'pixels', attrs: { pixels: '300px' } } ); }); it( 'should parse empty attributes', function() { expect( mailjs.parseElement( '[button borderRadius=""]' ) ).to.eql( { el: '[button borderRadius=""]', tag: 'button', attrs: { borderRadius: '' } } ) }); it( 'should parse only the first element', function() { expect( mailjs.parseElement( '[wrapper][pixels=300px]' ) ).to.eql( { el: '[wrapper]', tag: 'wrapper', attrs: {} } ) }); }); describe( 'generation', function() { before( function() { mailjs.config({ binds: { fontFamily: 'font-family:Helvetica, Arial, sans-serif' }, templates: { btn: { html: '<a style="!{style}color:#ffffff;width:!width;" href="!href">!label</a>', text: '!label: !href', binds: { style: '', width: '300px' } }, wrapper: { src: '', srcClose: '' } } }); }); after( function() { mailjs.config({}); }); it( 'should render simple text', function() { expect( mailjs.render({ src: 'This is a simple email.' }) ).to.eql( 'This is a simple email.' ); }); it( 'should support escapes', function() { expect( mailjs.render({ src: '\\[Hello, \\!firstName./\\]' }) ).to.eql( '[Hello, !firstName./]' ); }); it( 'should process simple binds', function() { expect( mailjs.render({ src: 'Hello, !firstName.', binds: { firstName: 'Jane' } }) ).to.eql( 'Hello, Jane.' ); }); it( 'should process simple binds using ES6-style template syntax - !{}', function() { expect( mailjs.render({ src: 'Hello, !{firstName}!{ space }!lastName.', binds: { firstName: 'Jane', lastName: 'Anderson', space: ' ' } }) ).to.eql( 'Hello, Jane Anderson.' ); }); it( 'should ignore !important and !doctype binds', function() { expect( mailjs.render({ src: 'font-size: 12px !important; !doctype;' }) ).to.eql( 'font-size: 12px !important; !doctype;' ); }); it( 'should ignore <!-- and <![ in bindings and trailing !', function() { expect( mailjs.render({ src: '<!-- comment --><!--\\[if microsoft] ... <\\[endif]--> !' }) ).to.eql( '<!-- comment --><!--[if microsoft] ... <[endif]--> !' ); }); it( 'should process templates', function() { expect( mailjs.render({ src: '[msg name="Jane"] and [msg].', binds: { name: 'Joe' }, templates: { msg: { src: 'a message for !name' } } }) ).to.eql( 'a message for Jane and a message for Joe.' ); }); it( 'should process tag-value templates', function() { expect( mailjs.render({ src: 'Email us at [email="support@apple.com"].', templates: { email: { html: '<a href="mailto:!email">!email</a>', text: '!email' } }, html: true }) ).to.eql( 'Email us at <a href="mailto:support@apple.com">support@apple.com</a>.' ); }); it( 'should process text & html templates', function() { expect( mailjs.render({ src: '[btn href="https://apple.com" label="Visit Apple"].' }) ).to.equal( 'Visit Apple: https://apple.com.' ); expect( mailjs.render({ src: '[btn href="https://apple.com" label="Visit Apple"].', html: true }) ).to.equal( '<a style="color:#ffffff;width:300px;" href="https://apple.com">Visit Apple</a>.' ); }); it( 'should throw when using unsupported close tags', function() { expect( function() { mailjs.render({ // here, btn does not support a closing tag src: '[btn href="https://apple.com" label="Visit Apple"]sample text[/btn].' }) }).to.throw( /Closing elements not supported/ ); }); it( 'should process config()ured binds', function() { expect( mailjs.render({ src: '[btn style="!fontFamily;" href="https://apple.com" label="Visit Apple"].', html: true }) ).to.equal( '<a style="font-family:Helvetica, Arial, sans-serif;color:#ffffff;width:300px;" href="https://apple.com">Visit Apple</a>.' ); }); it( 'should allow bindings to contain template references', function() { expect( mailjs.render({ src: 'This is !myBtn.', html: true, binds: { myBtn: '[btn href="https://apple.com" label="Visit Apple"]' } }) ).to.equal( 'This is <a style="color:#ffffff;width:300px;" href="https://apple.com">Visit Apple</a>.' ); }); it( 'should allow bindings to contain references to other bindings', function() { expect( mailjs.render({ src: 'It is true that !statement.', binds: { statement: '!name is a !profession', profession: 'programmer', name: '!firstName !lastName', firstName: 'Jill', lastName: 'Anderson' } }) ).to.equal( 'It is true that Jill Anderson is a programmer.' ); }); it( 'should render closed elements correctly', function() { expect( mailjs.render({ src: 'This is [boxed]contained[/boxed].', templates: { boxed: { src: '\\[', srcClose: '\\]' } } }) ).to.equal( 'This is [contained].' ); }); it( 'should render self-closed elements correctly', function() { expect( mailjs.render({ src: 'This is [boxed/].', templates: { boxed: { src: '\\[', srcClose: '\\]' } } }) ).to.equal( 'This is [].' ); }); it( 'should render process function templates', function() { expect( mailjs.render({ src: 'This is [dynamic].', templates: { dynamic: { src: function() { return 'generated'; } } } }) ).to.equal( 'This is generated.' ); }); it( 'should properly process scope.binding() calls', function() { expect( mailjs.render({ src: 'This is [dynamic].', templates: { dynamic: { src: function( scope ) { return 'generated using ' + scope.binding( 'name' ); } } }, binds: { name: 'Test' } }) ).to.equal( 'This is generated using Test.' ); }); it( 'should render process function bindings', function() { expect( mailjs.render({ src: 'This is !dynamic.', binds: { dynamic: function() { return '!name'; }, name: 'Test' } }) ).to.equal( 'This is Test.' ); }); it( 'should work with Scope.if()', function() { expect( mailjs.render({ src: function( scope ) { return '<a' + scope.if( 'style', ' style="!style"' ) + '>.'; }, binds: { style: 'color:#000;' } }) ).to.equal( '<a style="color:#000;">.' ); }); it( 'should support = assignment binds', function() { expect( mailjs.render({ src: '<a !=href !=style>', binds: { style: 'color:#000;', href: '' } }) ).to.equal( '<a style="color:#000;">' ); }); it( 'should support : assignment binds', function() { expect( mailjs.render({ src: '<a style="!:color;!:fontSize">', binds: { color: '', fontSize: '12px' } }) ).to.equal( '<a style="font-size:12px;">' ); }); it( 'should handle redefining nested binds', function() { expect( mailjs.render({ src: function( scope ) { return '[b width="300px;"]' }, templates: { a: { src: '!width' }, b: { src: '[a width=!width]' } } }) ).to.equal( '300px;' ); }); it( 'should handle default attributes', function() { expect( mailjs.render({ src: function( scope ) { return '[b]' }, templates: { a: { src: '!width', }, b: { src: '[a width=!width]', binds: { width: '40px' } } } }) ).to.equal( '40px' ); }); it( 'should support Scope.pixels()', function() { expect( mailjs.render({ src: '[pixels=300px]' }) ).to.equal( '300' ); }); it( 'should support css inlining', function() { expect( mailjs.render({ src: '<h1 class="foo">test</h1>', html: true, css: '.foo { color: red; }' }) ).to.equal( '<h1 class="foo" style="color: red;">test</h1>' ); }); it( 'should process tdiv\'s', function() { expect( mailjs.render({ src: '[tdiv class="foo"][/tdiv]', html: true }) ).to.eql( '<table border="0" cellpadding="0" cellspacing="0" class="foo" style="width:100%;"><tr><td></td></tr></table>' ); }); it( 'should process nested tdiv\'s', function() { expect( mailjs.render({ src: '[outer][/outer]', html: true, templates: { outer: { html: '[tdiv class="outer-cls"]', htmlClose: '[/tdiv]' } } }) ).to.eql( '<table border="0" cellpadding="0" cellspacing="0" class="outer-cls" style="width:100%;"><tr><td></td></tr></table>' ); }); it( 'should add css to existing style tags', function() { expect( mailjs.render({ src: `[notificationBody]`, html: true, css: ` .foo { color: #fff; background-color: #ededed; } `, templates: { notificationBody: { html: '<table border="0" cellpadding="0" cellspacing="0" class="foo" style="width:100%;"><tr><td></td></tr></table>' } } }) ).to.eql( '<table border="0" cellpadding="0" cellspacing="0" class="foo" style="color: #fff; background-color: #ededed; width: 100%;" width="100%" bgcolor="#ededed"><tr><td></td></tr></table>' ); }); it( 'should support buttons', function() { expect( mailjs.render({ src: '[button label="View" href="http://apple.com"]', html: true }) ).to.eql( '<table border="0" cellpadding="0" cellspacing="0"><tr><td align="center" width="300" height="40" bgcolor="#d62828" style="color:#ffffff;display:block;">' + '<a href="http://apple.com" style="color:#ffffff;font-size:16px;font-weight:bold;font-family:sans-serif;text-decoration:none;line-height:40px;width:100%;display:inline-block">View</a>' + '</td></tr></table>' ); }); it( 'should support rounded buttons', function() { expect( mailjs.render({ src: '[button label="View" href="http://apple.com" borderRadius="6px"]', html: true }) ).to.eql( '<div><!--[if mso]><v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://apple.com" style="height:40px;v-text-anchor:middle;width:300px;" arcsize="10%" stroke="f" fillcolor="#d62828"><w:anchorlock/><center style="color:#ffffff;font-family:sans-serif;font-size:16px;font-weight:bold;">View</center></v:roundrect><![endif]--><![if !mso]><table border="0" cellpadding="0" cellspacing="0"><tr><td align="center" width="300" height="40" bgcolor="#d62828" style="-moz-border-radius:6px;-webkit-border-radius:6px;border-radius:6px;;color:#ffffff;display:block;"><a href="http://apple.com" style="color:#ffffff;font-size:16px;font-weight:bold;font-family:sans-serif;text-decoration:none;line-height:40px;width:100%;display:inline-block">View</a></td></tr></table><![endif]></div>' ); }); }); describe( 'generation with boilerplate', function() { before( function() { mailjs.config({ }); }); after( function() { mailjs.config({}); }); it( 'should render still render simple text', function() { expect( mailjs.render({ src: 'This is a simple email.' }) ).to.eql( 'This is a simple email.' ); }); });