You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
8.2 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. 'use strict'
  2. const test = require('tape')
  3. const request = require('req-then')
  4. const localWebServer = require('../')
  5. const http = require('http')
  6. const PassThrough = require('stream').PassThrough
  7. function launchServer (app, options) {
  8. options = options || {}
  9. const path = `http://localhost:8100${options.path || '/'}`
  10. const server = http.createServer(app.callback())
  11. return server.listen(options.port || 8100, () => {
  12. const req = request(path, options.reqOptions)
  13. if (options.onSuccess) req.then(options.onSuccess)
  14. if (!options.leaveOpen) req.then(() => server.close())
  15. req.catch(err => console.error('LAUNCH ERROR', err.stack))
  16. })
  17. }
  18. function checkResponse (t, status, body) {
  19. return function (response) {
  20. if (status) t.strictEqual(response.res.statusCode, status)
  21. if (body) t.ok(body.test(response.data))
  22. }
  23. }
  24. test('serve-index', function (t) {
  25. t.plan(2)
  26. const app = localWebServer({
  27. log: { format: 'none' },
  28. serveIndex: {
  29. path: __dirname + '/fixture',
  30. options: {
  31. icons: true
  32. }
  33. }
  34. })
  35. launchServer(app, { onSuccess: response => {
  36. t.ok(/listing directory/.test(response.data))
  37. t.ok(/class="icon/.test(response.data))
  38. }})
  39. })
  40. test('single page app', function (t) {
  41. t.plan(6)
  42. const app = localWebServer({
  43. log: { format: 'none' },
  44. static: { root: __dirname + '/fixture/spa' },
  45. spa: 'one.txt'
  46. })
  47. const server = http.createServer(app.callback())
  48. server.listen(8100, () => {
  49. /* text/html requests for missing files redirect to spa */
  50. request('http://localhost:8100/asdf', { headers: { accept: 'text/html' } })
  51. .then(checkResponse(t, 200, /one/))
  52. /* html requests for missing files with extensions do not redirect to spa */
  53. .then(() => request('http://localhost:8100/asdf.txt', { headers: { accept: 'text/html' } }))
  54. .then(checkResponse(t, 404))
  55. /* existing static file */
  56. .then(() => request('http://localhost:8100/two.txt'))
  57. .then(checkResponse(t, 200, /two/))
  58. /* not a text/html request - does not redirect to spa */
  59. .then(() => request('http://localhost:8100/asdf'))
  60. .then(checkResponse(t, 404))
  61. .then(server.close.bind(server))
  62. })
  63. })
  64. test('log: common', function (t) {
  65. t.plan(1)
  66. const stream = PassThrough()
  67. stream.on('readable', () => {
  68. let chunk = stream.read()
  69. if (chunk) t.ok(/GET/.test(chunk.toString()))
  70. })
  71. const app = localWebServer({
  72. log: {
  73. format: 'common',
  74. options: {
  75. stream: stream
  76. }
  77. }
  78. })
  79. launchServer(app)
  80. })
  81. test('compress', function (t) {
  82. t.plan(1)
  83. const app = localWebServer({
  84. compress: true,
  85. log: { format: 'none' },
  86. static: { root: __dirname + '/fixture' }
  87. })
  88. launchServer(
  89. app,
  90. {
  91. reqOptions: { headers: { 'Accept-Encoding': 'gzip' } },
  92. path: '/big-file.txt',
  93. onSuccess: response => {
  94. t.strictEqual(response.res.headers['content-encoding'], 'gzip')
  95. }
  96. }
  97. )
  98. })
  99. test('mime', function (t) {
  100. t.plan(2)
  101. const app = localWebServer({
  102. log: { format: 'none' },
  103. static: { root: __dirname + '/fixture' },
  104. mime: { 'text/plain': [ 'php' ] }
  105. })
  106. launchServer(app, { path: '/something.php', onSuccess: response => {
  107. t.strictEqual(response.res.statusCode, 200)
  108. t.ok(/text\/plain/.test(response.res.headers['content-type']))
  109. }})
  110. })
  111. test('forbid', function (t) {
  112. t.plan(2)
  113. const app = localWebServer({
  114. log: { format: 'none' },
  115. static: { root: __dirname + '/fixture/forbid' },
  116. forbid: [ '*.php', '*.html' ]
  117. })
  118. const server = launchServer(app, { leaveOpen: true })
  119. request('http://localhost:8100/two.php')
  120. .then(response => {
  121. t.strictEqual(response.res.statusCode, 403)
  122. request('http://localhost:8100/one.html')
  123. .then(response => {
  124. t.strictEqual(response.res.statusCode, 403)
  125. server.close()
  126. })
  127. })
  128. })
  129. test('rewrite: local', function (t) {
  130. t.plan(1)
  131. const app = localWebServer({
  132. log: { format: 'none' },
  133. static: { root: __dirname + '/fixture/rewrite' },
  134. rewrite: [ { from: '/two.html', to: '/one.html' } ]
  135. })
  136. launchServer(app, { path: '/two.html', onSuccess: response => {
  137. t.ok(/one/.test(response.data))
  138. }})
  139. })
  140. test('mock: simple response', function (t) {
  141. t.plan(2)
  142. const app = localWebServer({
  143. log: { format: 'none' },
  144. mocks: [
  145. { route: '/test', response: { body: 'test' } }
  146. ]
  147. })
  148. launchServer(app, { path: '/test', onSuccess: response => {
  149. t.strictEqual(response.res.statusCode, 200)
  150. t.ok(/test/.test(response.data))
  151. }})
  152. })
  153. test('mock: method request filter', function (t) {
  154. t.plan(3)
  155. const app = localWebServer({
  156. log: { format: 'none' },
  157. mocks: [
  158. {
  159. route: '/test',
  160. request: { method: 'POST' },
  161. response: { body: 'test' }
  162. }
  163. ]
  164. })
  165. const server = http.createServer(app.callback())
  166. server.listen(8100, () => {
  167. request('http://localhost:8100/test')
  168. .then(checkResponse(t, 404))
  169. .then(() => request('http://localhost:8100/test', { data: 'something' }))
  170. .then(checkResponse(t, 200, /test/))
  171. .then(server.close.bind(server))
  172. })
  173. })
  174. test('mock: accepts request filter', function (t) {
  175. t.plan(3)
  176. const app = localWebServer({
  177. log: { format: 'none' },
  178. mocks: [
  179. {
  180. route: '/test',
  181. request: { accepts: 'text' },
  182. response: { body: 'test' }
  183. }
  184. ]
  185. })
  186. const server = http.createServer(app.callback())
  187. server.listen(8100, () => {
  188. request('http://localhost:8100/test', { headers: { Accept: '*/json' } })
  189. .then(checkResponse(t, 404))
  190. .then(() => request('http://localhost:8100/test', { headers: { Accept: 'text/plain' } }))
  191. .then(checkResponse(t, 200, /test/))
  192. .then(server.close.bind(server))
  193. })
  194. })
  195. test('mock: responses array', function (t) {
  196. t.plan(4)
  197. const app = localWebServer({
  198. log: { format: 'none' },
  199. mocks: [
  200. {
  201. route: '/test',
  202. responses: [
  203. { request: { method: 'GET' }, response: { body: 'get' } },
  204. { request: { method: 'POST' }, response: { body: 'post' } }
  205. ]
  206. }
  207. ]
  208. })
  209. const server = http.createServer(app.callback())
  210. server.listen(8100, () => {
  211. request('http://localhost:8100/test')
  212. .then(checkResponse(t, 200, /get/))
  213. .then(() => request('http://localhost:8100/test', { method: 'POST' }))
  214. .then(checkResponse(t, 200, /post/))
  215. .then(server.close.bind(server))
  216. })
  217. })
  218. test('mock: response function', function (t) {
  219. t.plan(4)
  220. const app = localWebServer({
  221. log: { format: 'none' },
  222. mocks: [
  223. {
  224. route: '/test',
  225. responses: [
  226. { request: { method: 'GET' }, response: ctx => ctx.body = 'get' },
  227. { request: { method: 'POST' }, response: ctx => ctx.body = 'post' }
  228. ]
  229. }
  230. ]
  231. })
  232. const server = http.createServer(app.callback())
  233. server.listen(8100, () => {
  234. request('http://localhost:8100/test')
  235. .then(checkResponse(t, 200, /get/))
  236. .then(() => request('http://localhost:8100/test', { method: 'POST' }))
  237. .then(checkResponse(t, 200, /post/))
  238. .then(server.close.bind(server))
  239. })
  240. })
  241. test('mock: response function args', function (t) {
  242. t.plan(2)
  243. const app = localWebServer({
  244. log: { format: 'none' },
  245. mocks: [
  246. {
  247. route: '/test/:one',
  248. responses: [
  249. { request: { method: 'GET' }, response: (ctx, one) => ctx.body = one }
  250. ]
  251. }
  252. ]
  253. })
  254. const server = http.createServer(app.callback())
  255. server.listen(8100, () => {
  256. request('http://localhost:8100/test/yeah')
  257. .then(checkResponse(t, 200, /yeah/))
  258. .then(server.close.bind(server))
  259. })
  260. })
  261. test('mock: async response function', function (t) {
  262. t.plan(2)
  263. const app = localWebServer({
  264. log: { format: 'none' },
  265. mocks: [
  266. {
  267. route: '/test',
  268. responses: {
  269. response: function (ctx) {
  270. return new Promise((resolve, reject) => {
  271. setTimeout(() => {
  272. ctx.body = 'test'
  273. resolve()
  274. }, 10)
  275. })
  276. }
  277. }
  278. }
  279. ]
  280. })
  281. const server = http.createServer(app.callback())
  282. server.listen(8100, () => {
  283. request('http://localhost:8100/test')
  284. .then(checkResponse(t, 200, /test/))
  285. .then(server.close.bind(server))
  286. })
  287. })