Skip to content

Commit b5f0513

Browse files
committed
add allow_partial_request_body and allow_partial_expected_body
1 parent 671a173 commit b5f0513

10 files changed

Lines changed: 259 additions & 24 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ b.js
88
package-lock.json
99
# index.html
1010
/lib/routes.js
11-
/misc/test.example.json
11+
/misc/test.example.json
12+
playground.*

.npmignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ specs
77
examples
88
.circleci
99
index.html
10-
misc
10+
misc
11+
playground.*

Readme.md

Lines changed: 107 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,15 @@ const APIModelObject = {
156156
}]
157157
},
158158
"request_body_equal": { // this property will work with PUT, POST, DELETE, PATCH only
159-
"status": 404,
160-
"not_equal_response": { // this field is optional, default is {"data": "invalid request"}
161-
"success": false
162-
},
163-
"expected_body": { // request body should equal expected_body property
164-
"username": "test_",
165-
"password": "test_pass"
166-
}
159+
"allow_partial_request_body": true, // allow send not all keys and get success response
160+
"status": 404,
161+
"not_equal_response": { // this field is optional, default is {"data": "invalid request"}
162+
"success": false
163+
},
164+
"expected_body": { // request body should equal expected_body property
165+
"username": "test",
166+
"password": "test_pass"
167+
}
167168
},
168169
"response": { // response is option field, default is {ok: 'OK'}
169170
"example": "example GET"
@@ -472,7 +473,10 @@ const indexHtmlText = await fetch('http://localhost:8081/', {method: 'GET'}).the
472473
```js
473474
const fakeServer = require('test-fake-server')
474475
const fetch = require('node-fetch')
475-
const model_obj = {
476+
477+
// full equalty check
478+
async function callToServer() {
479+
const model_obj = {
476480
"port": "8081",
477481
"debug": true, // if this prop exists log will show all results in console, defailt is false
478482
"api": [{
@@ -491,18 +495,109 @@ const model_obj = {
491495
"response": {
492496
"success": true
493497
}
494-
}]
498+
}]
499+
}
500+
501+
const serser = await fakeServer(model_obj)
502+
503+
const body_equal_success = await fetch('http://localhost:8081/test', {
504+
method: 'POST',
505+
headers: {'Content-Type': 'application/json'},
506+
body: JSON.stringify({"username": "test_", "password": "test_pass"})
507+
}).then((res) => res.text())
508+
// {"success":true}
509+
console.log(body_equal_success)
510+
511+
const body_not_equal = await fetch('http://localhost:8081/test', {
512+
method: 'POST',
513+
headers: {'Content-Type': 'application/json'},
514+
body: JSON.stringify({
515+
"username": "test_1",
516+
"password": "test_pass"
517+
})
518+
}).then((res) => res.text())
519+
// {"success": false}
520+
console.log(body_not_equal)
521+
await serser.stop()
495522
}
496523

524+
async function callToServerPartialRequest() {
525+
const model_obj = {
526+
"port": "8081",
527+
"debug": true, // if this prop exists log will show all results in console, defailt is false
528+
"api": [{
529+
"method": "POST",
530+
"path": "/user",
531+
"request_body_equal": {
532+
"status": 404,
533+
"not_equal_response": { // this field is optional, default is {"data": "invalid request"}
534+
"success": false
535+
},
536+
"allow_partial_request_body": true,
537+
"expected_body": {
538+
"username": "test_",
539+
"password": "test_pass"
540+
}
541+
},
542+
"response": {
543+
"success": true
544+
}
545+
}]
546+
}
547+
548+
const serser = await fakeServer(model_obj)
497549

550+
const body_equal_success = await fetch('http://localhost:8081/test', {
551+
method: 'POST',
552+
headers: {'Content-Type': 'application/json'},
553+
body: JSON.stringify({"username": "test_",}) // partial body matches
554+
}).then((res) => res.text())
555+
// {"success":true}
556+
console.log(body_equal_success)
557+
558+
const body_not_equal = await fetch('http://localhost:8081/test', {
559+
method: 'POST',
560+
headers: {'Content-Type': 'application/json'},
561+
body: JSON.stringify({
562+
"username": "test_1",
563+
"password": "test_pass"
564+
})
565+
}).then((res) => res.text())
566+
// {"success": false}
567+
console.log(body_not_equal)
568+
await serser.stop()
569+
}
570+
571+
async function callToServerPartialExpected() {
572+
const model_obj = {
573+
"port": "8081",
574+
"debug": true, // if this prop exists log will show all results in console, defailt is false
575+
"api": [{
576+
"method": "POST",
577+
"path": "/user",
578+
"request_body_equal": {
579+
"status": 404,
580+
"not_equal_response": { // this field is optional, default is {"data": "invalid request"}
581+
"success": false
582+
},
583+
"allow_partial_expected_body": true,
584+
"expected_body": {
585+
"username": "test_",
586+
"password": "test_pass"
587+
}
588+
},
589+
"response": {
590+
"success": true
591+
}
592+
}]
593+
}
498594

499-
async function callToServer() {
500595
const serser = await fakeServer(model_obj)
501596

502597
const body_equal_success = await fetch('http://localhost:8081/test', {
503598
method: 'POST',
504599
headers: {'Content-Type': 'application/json'},
505-
body: JSON.stringify({"username": "test_", "password": "test_pass"})
600+
body: JSON.stringify({"username": "test_", "password": "test_pass", "x": 2, "Y": 2}) // more that required keys are in request body
506601
}).then((res) => res.text())
507602
// {"success":true}
508603
console.log(body_equal_success)

lib/commons/equal_obj.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const { compareToPattern } = require('sat-utils')
2+
13
const is_arguments = function(object) {
24
return Object.prototype.toString.call(object) == '[object Arguments]'
35
}
@@ -22,7 +24,7 @@ const get_to_string = (arg) => {
2224
return Object.prototype.toString.call(arg)
2325
}
2426

25-
function deep_equal(actual, expected) {
27+
function _deep_equal(actual, expected) {
2628
if(get_to_string(actual) !== get_to_string(expected)) {
2729
return false
2830
} else if(actual === expected) {
@@ -72,4 +74,17 @@ function obj_equiv(act, exp) {
7274
return typeof act === typeof exp
7375
}
7476

77+
78+
function deep_equal(actual, expected, {allow_partial_request_body, allow_partial_expected_body} = {}) {
79+
if(allow_partial_request_body && allow_partial_expected_body) {
80+
return compareToPattern(expected, actual).result || compareToPattern(actual, expected).result;
81+
} else if (allow_partial_request_body) {
82+
return compareToPattern(expected, actual).result
83+
} else if(allow_partial_expected_body) {
84+
return compareToPattern(actual, expected).result
85+
} else {
86+
return _deep_equal(actual, expected)
87+
}
88+
}
89+
7590
module.exports = {deep_equal}

lib/routing_templates/build_koa_router_model/body_equal.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ const {build_response_default} = require('./body_default')
88
*/
99
function build_request_body_equal_response(body_equal, path, http_method) {
1010

11-
const {not_equal_response = {data: 'invalid request'}, status = 404, expected_body} = body_equal
11+
const {not_equal_response = {data: 'invalid request'}, status = 404, expected_body, allow_partial_request_body, allow_partial_expected_body} = body_equal
1212

1313
return `\n
14-
if(!deep_equal(ctx.request.body, ${build_response_default(expected_body, path, http_method)})) {
14+
if(!deep_equal(
15+
ctx.request.body,
16+
${build_response_default(expected_body, path, http_method)},
17+
{allow_partial_request_body: ${allow_partial_request_body}, allow_partial_expected_body: ${allow_partial_expected_body}})
18+
) {
1519
ctx.status = ${status}
1620
ctx.body = ${build_response_default(not_equal_response, path, http_method)}
1721
return ctx

lib/server_worker/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
// @ts-check
12
const Koa = require('koa')
2-
const Router = require('koa-router')
3+
const Router = require('@koa/router')
34
const bodyParser = require('koa-bodyparser')
45
const cors = require('@koa/cors')
56

@@ -13,6 +14,7 @@ module.exports = function(model) {
1314

1415
function require_module_from_string(src, filename = '') {
1516
const Module = module.constructor
17+
// @ts-ignore
1618
const mod = new Module()
1719
mod._compile(src, filename)
1820
return mod.exports
@@ -24,6 +26,7 @@ module.exports = function(model) {
2426

2527
// if fake server model contains authorization property
2628
// next execution will set koa-bearer-token middleware
29+
// @ts-ignore
2730
set_authorization_middleware(app, model)
2831
app.use(cors())
2932

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "test-fake-server",
3-
"version": "2.6.0",
3+
"version": "2.7.0",
44
"description": "simple way to create node http server",
55
"main": "index.js",
66
"bin": {
@@ -34,19 +34,19 @@
3434
"url": "https://github.com/potapovDim/test-fake-server/issues"
3535
},
3636
"dependencies": {
37-
"@koa/cors": "^2.2.3",
37+
"@koa/cors": "^3.4.2",
38+
"@koa/router": "^12.0.0",
39+
"koa": "^2.13.4",
3840
"koa-bearer-token": "^1.0.0",
3941
"koa-bodyparser": "^4.3.0",
4042
"koa-logger": "^3.2.0",
41-
"koa-router": "^7.4.0",
42-
"koa": "^2.12.0",
4343
"minimist": "^1.2.5",
44-
"node-fetch": "^2.6.1"
44+
"node-fetch": "^2.6.1",
45+
"sat-utils": "^1.0.1"
4546
},
4647
"homepage": "https://github.com/potapovDim/test-fake-server#readme",
4748
"devDependencies": {
4849
"ajv": "^6.12.2",
49-
"axios": "^0.19.2",
5050
"chai": "^4.1.2",
5151
"mocha": "^5.2.0"
5252
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const fakeServer = require('../index')
2+
const fetch = require('node-fetch')
3+
const {expect} = require('chai')
4+
5+
describe('Body equal gets allow_partial_expected_body', () => {
6+
let server = null
7+
const model_obj = {
8+
"port": 8888,
9+
"api": [{
10+
"method": "POST",
11+
"path": "/user",
12+
"request_body_equal": {
13+
"status": 404,
14+
"allow_partial_expected_body": true,
15+
"expected_body": {
16+
"username": "test",
17+
"password": "test_pass"
18+
}
19+
},
20+
"response": {
21+
"success": true
22+
}
23+
}]
24+
}
25+
beforeEach(async () => {
26+
server = await fakeServer(model_obj)
27+
})
28+
afterEach(async () => {
29+
await server.stop()
30+
})
31+
32+
it('success', async function() {
33+
const responseBody = await fetch('http://localhost:8888/user', {
34+
method: 'POST',
35+
headers: {'Content-Type': 'application/json'},
36+
body: JSON.stringify({"username": "test", "password": "test_pass"})
37+
}).then((res) => res.json())
38+
expect(responseBody.success).to.eql(true)
39+
})
40+
41+
it('[more_than_required_keys] success', async function() {
42+
const responseBody = await fetch('http://localhost:8888/user', {
43+
method: 'POST',
44+
headers: {'Content-Type': 'application/json'},
45+
body: JSON.stringify({"username": "test", "password": "test_pass", "x": 2, "Y": 2})
46+
}).then((res) => res.json())
47+
expect(responseBody.success).to.eql(true)
48+
})
49+
50+
it('invalid', async function() {
51+
const responseBody = await fetch('http://localhost:8888/user', {
52+
method: 'POST',
53+
headers: {'Content-Type': 'application/json'},
54+
body: JSON.stringify({"username": "test---", "password": "test_pass"})
55+
}).then((res) => res.json())
56+
expect(responseBody.data).to.eql('invalid request')
57+
})
58+
})
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const fakeServer = require('../index')
2+
const fetch = require('node-fetch')
3+
const {expect} = require('chai')
4+
5+
describe('Body equal gets allow_partial_request_body', () => {
6+
let server = null
7+
const model_obj = {
8+
"port": 8888,
9+
"api": [{
10+
"method": "POST",
11+
"path": "/user",
12+
"request_body_equal": {
13+
"status": 404,
14+
"allow_partial_request_body": true,
15+
"expected_body": {
16+
"username": "test",
17+
"password": "test_pass"
18+
}
19+
},
20+
"response": {
21+
"success": true
22+
}
23+
}]
24+
}
25+
beforeEach(async () => {
26+
server = await fakeServer(model_obj)
27+
})
28+
afterEach(async () => {
29+
await server.stop()
30+
})
31+
32+
it('success', async function() {
33+
const responseBody = await fetch('http://localhost:8888/user', {
34+
method: 'POST',
35+
headers: {'Content-Type': 'application/json'},
36+
body: JSON.stringify({"username": "test"})
37+
}).then((res) => res.json())
38+
expect(responseBody.success).to.eql(true)
39+
})
40+
41+
it('[not_all_keys] success', async function() {
42+
const responseBody = await fetch('http://localhost:8888/user', {
43+
method: 'POST',
44+
headers: {'Content-Type': 'application/json'},
45+
body: JSON.stringify({"username": "test"})
46+
}).then((res) => res.json())
47+
expect(responseBody.success).to.eql(true)
48+
})
49+
50+
it('invalid', async function() {
51+
const responseBody = await fetch('http://localhost:8888/user', {
52+
method: 'POST',
53+
headers: {'Content-Type': 'application/json'},
54+
body: JSON.stringify({"username": "test---", "password": "test_pass"})
55+
}).then((res) => res.json())
56+
expect(responseBody.data).to.eql('invalid request')
57+
})
58+
})

0 commit comments

Comments
 (0)