index.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. const request = require('supertest')
  2. const views = require('../src')
  3. const path = require('path')
  4. const Koa = require('koa')
  5. const should = require('should')
  6. describe('koa-views', () => {
  7. it('have a render method', done => {
  8. const app = new Koa().use(views()).use(ctx => {
  9. should(ctx.render).be.ok()
  10. should(ctx.render).be.a.Function()
  11. should(ctx.response.render).be.equal(ctx.render)
  12. })
  13. request(app.listen())
  14. .get('/')
  15. .expect(404, done)
  16. })
  17. it('have a render method by app.context', done => {
  18. const app = new Koa()
  19. const render = views()()
  20. app.context.render = render
  21. app.response.render = render
  22. app.use(ctx => {
  23. should(ctx.render).be.ok()
  24. should(ctx.render).be.a.Function()
  25. should(ctx.response.render).be.equal(ctx.render)
  26. })
  27. request(app.listen())
  28. .get('/')
  29. .expect(404, done)
  30. })
  31. it('default to html', done => {
  32. const app = new Koa().use(views(__dirname)).use(ctx => {
  33. return ctx.render('./fixtures/basic')
  34. })
  35. request(app.listen())
  36. .get('/')
  37. .expect('Content-Type', /html/)
  38. .expect(/basic:html/)
  39. .expect(200, done)
  40. })
  41. it('default to html', done => {
  42. const app = new Koa()
  43. const render = views(__dirname)()
  44. app.context.render = render
  45. app.response.render = render
  46. app.use(ctx => {
  47. return ctx.render('./fixtures/basic')
  48. })
  49. request(app.listen())
  50. .get('/')
  51. .expect('Content-Type', /html/)
  52. .expect(/basic:html/)
  53. .expect(200, done)
  54. })
  55. it('autoRender is false', done => {
  56. const app = new Koa().use(views(__dirname, { autoRender: false, extension: 'ejs' })).use(async (ctx) => {
  57. const res = await ctx.render('./fixtures/basic')
  58. ctx.body = res
  59. })
  60. request(app.listen())
  61. .get('/')
  62. .expect('Content-Type', /html/)
  63. .expect(/basic:ejs/)
  64. .expect(200, done)
  65. })
  66. it('autoRender is false by app.context', done => {
  67. const app = new Koa()
  68. const render = views(__dirname, { autoRender: false, extension: 'ejs' })()
  69. app.context.render = render
  70. app.response.render = render
  71. app.use(async (ctx) => {
  72. const res = await ctx.render('./fixtures/basic')
  73. ctx.body = res
  74. })
  75. request(app.listen())
  76. .get('/')
  77. .expect('Content-Type', /html/)
  78. .expect(/basic:ejs/)
  79. .expect(200, done)
  80. })
  81. it('default to [ext] if a default engine is set', done => {
  82. const app = new Koa()
  83. .use(views(__dirname, { extension: 'pug' }))
  84. .use(ctx => {
  85. return ctx.render('./fixtures/basic')
  86. })
  87. request(app.listen())
  88. .get('/')
  89. .expect('Content-Type', /html/)
  90. .expect(/basic:jade/)
  91. .expect(200, done)
  92. })
  93. it('set and render state', done => {
  94. const app = new Koa()
  95. .use(views(__dirname, { extension: 'pug' }))
  96. .use(ctx => {
  97. ctx.state.engine = 'pug'
  98. return ctx.render('./fixtures/global-state')
  99. })
  100. request(app.listen())
  101. .get('/')
  102. .expect('Content-Type', /html/)
  103. .expect(/basic:pug/)
  104. .expect(200, done)
  105. })
  106. // #25
  107. it('works with circular references in state', done => {
  108. const app = new Koa()
  109. .use(views(__dirname, { extension: 'pug' }))
  110. .use(function (ctx) {
  111. ctx.state = {
  112. a: {},
  113. app
  114. }
  115. ctx.state.a.a = ctx.state.a
  116. return ctx.render('./fixtures/global-state', {
  117. app,
  118. b: this.state,
  119. engine: 'pug'
  120. })
  121. })
  122. request(app.listen())
  123. .get('/')
  124. .expect('Content-Type', /html/)
  125. .expect(/basic:pug/)
  126. .expect(200, done)
  127. })
  128. // #138
  129. it('works with bigint in state', done => {
  130. const app = new Koa()
  131. .use(views(__dirname, { extension: 'pug' }))
  132. .use(function (ctx) {
  133. ctx.state = {
  134. a: { x: 132n },
  135. app
  136. }
  137. return ctx.render('./fixtures/global-state', {
  138. app,
  139. b: this.state,
  140. engine: 'pug'
  141. })
  142. })
  143. request(app.listen())
  144. .get('/')
  145. .expect('Content-Type', /html/)
  146. .expect(/basic:pug/)
  147. .expect(200, done)
  148. })
  149. it('`map` given `engine` to given file `ext`', done => {
  150. const app = new Koa()
  151. .use(views(__dirname, { map: { html: 'underscore' } }))
  152. .use(ctx => {
  153. ctx.state.engine = 'underscore'
  154. return ctx.render('./fixtures/underscore')
  155. })
  156. request(app.listen())
  157. .get('/')
  158. .expect('Content-Type', /html/)
  159. .expect(/basic:underscore/)
  160. .expect(200, done)
  161. })
  162. it('merges global and local state ', done => {
  163. const app = new Koa()
  164. .use(views(__dirname, { extension: 'pug' }))
  165. .use(ctx => {
  166. ctx.state.engine = 'pug'
  167. return ctx.render('./fixtures/state', {
  168. type: 'basic'
  169. })
  170. })
  171. request(app.listen())
  172. .get('/')
  173. .expect('Content-Type', /html/)
  174. .expect(/basic:pug/)
  175. .expect(200, done)
  176. })
  177. it('call to the next middleware if this.render is already defined', done => {
  178. const app = new Koa()
  179. .use((ctx, next) => {
  180. ctx.render = true
  181. return next()
  182. })
  183. .use(views())
  184. .use(ctx => {
  185. ctx.body = 'hello'
  186. })
  187. request(app.listen())
  188. .get('/')
  189. .expect('hello')
  190. .expect(200, done)
  191. })
  192. it('allows view options to be passed in', done => {
  193. const app = new Koa()
  194. .use(
  195. views(__dirname, {
  196. map: { hbs: 'handlebars' },
  197. options: {
  198. helpers: {
  199. uppercase: str => str.toUpperCase()
  200. },
  201. partials: {
  202. subTitle: './view-options-partial'
  203. }
  204. }
  205. })
  206. )
  207. .use(ctx => {
  208. ctx.state = { title: 'my title', author: 'queckezz' }
  209. return ctx.render('./fixtures/view-options.hbs')
  210. })
  211. const server = request(app.listen())
  212. server
  213. .get('/')
  214. .expect(/MY TITLE/)
  215. .expect(200, () => {
  216. server
  217. .get('/')
  218. .expect(/MY TITLE/)
  219. .expect(200, done)
  220. })
  221. })
  222. // #23 && #27
  223. it('given a directory it should try to require index.[ext]', done => {
  224. const app = new Koa().use(views(__dirname)).use(ctx => {
  225. return ctx.render('./fixtures')
  226. })
  227. request(app.listen())
  228. .get('/')
  229. .expect(/defaults-to-index/)
  230. .expect(200, done)
  231. })
  232. // #43
  233. it('it should not overwrite an extension when given one', done => {
  234. const app = new Koa().use(views(__dirname)).use(ctx => {
  235. return ctx.render('./fixtures/basic.ejs')
  236. })
  237. request(app.listen())
  238. .get('/')
  239. .expect(/basic:ejs/)
  240. .expect(200, done)
  241. })
  242. it('it should use an engineSource other than consolidate when provided', done => {
  243. const app = new Koa()
  244. .use(
  245. views(__dirname, {
  246. engineSource: {
  247. foo: () => Promise.resolve('hello')
  248. }
  249. })
  250. )
  251. .use(ctx => {
  252. return ctx.render('./fixtures/basic.foo')
  253. })
  254. request(app.listen())
  255. .get('/')
  256. .expect(/hello/)
  257. .expect(200, done)
  258. })
  259. // #82
  260. describe('extension is ejs, frist visit basic.html then visit basic should render basic.ejs', () => {
  261. const app = new Koa()
  262. .use(
  263. views(__dirname, {
  264. extension: 'ejs'
  265. })
  266. )
  267. .use((ctx, next) => {
  268. if (ctx.path === '/html') {
  269. return ctx.render('./fixtures/basic.html')
  270. }
  271. return next()
  272. })
  273. .use((ctx, next) => {
  274. if (ctx.path === '/ejs') {
  275. return ctx.render('./fixtures/basic')
  276. }
  277. return next()
  278. })
  279. const server = request(app.listen())
  280. it('first visit html', done => {
  281. server
  282. .get('/html')
  283. .expect(/basic:html/)
  284. .expect(200, done)
  285. })
  286. it('then visit ejs should render basic basic.ejs', done => {
  287. server
  288. .get('/ejs')
  289. .expect(/basic:ejs/)
  290. .expect(200, done)
  291. })
  292. })
  293. // #87
  294. it('name with dot', done => {
  295. const app = new Koa().use(views(__dirname)).use(ctx => {
  296. return ctx.render('./fixtures/basic.test')
  297. })
  298. request(app.listen())
  299. .get('/')
  300. .expect('Content-Type', /html/)
  301. .expect(/basic:html/)
  302. .expect(200, done)
  303. })
  304. // #94
  305. it('nunjucks with nunjucksEnv', done => {
  306. const nunjucks = require('nunjucks')
  307. const env = new nunjucks.Environment(
  308. new nunjucks.FileSystemLoader(path.join(__dirname, 'fixtures'))
  309. )
  310. env.addFilter('shorten', (str, count) => {
  311. return str.slice(0, count || 5)
  312. })
  313. const app = new Koa()
  314. .use(
  315. views(path.join(__dirname, 'fixtures'), {
  316. options: {
  317. nunjucksEnv: env
  318. },
  319. map: { html: 'nunjucks' }
  320. })
  321. )
  322. .use(ctx => {
  323. return ctx.render('nunjucks-filter', {
  324. message: 'this is a long message'
  325. })
  326. })
  327. request(app.listen())
  328. .get('/')
  329. .expect('Content-Type', /html/)
  330. .expect(/this </)
  331. .expect(200, done)
  332. })
  333. it('nunjucks with nunjucksEnv by app.context', done => {
  334. const nunjucks = require('nunjucks')
  335. const env = new nunjucks.Environment(
  336. new nunjucks.FileSystemLoader(path.join(__dirname, 'fixtures'))
  337. )
  338. env.addFilter('shorten', (str, count) => {
  339. return str.slice(0, count || 5)
  340. })
  341. const app = new Koa()
  342. const render = views(path.join(__dirname, 'fixtures'), {
  343. options: {
  344. nunjucksEnv: env
  345. },
  346. map: { html: 'nunjucks' }
  347. })()
  348. app.context.render = render
  349. app.response.render = render
  350. app.use(ctx => {
  351. return ctx.render('nunjucks-filter', {
  352. message: 'this is a long message'
  353. })
  354. })
  355. request(app.listen())
  356. .get('/')
  357. .expect('Content-Type', /html/)
  358. .expect(/this </)
  359. .expect(200, done)
  360. })
  361. })