Skip to content

Commit

Permalink
Implement W3C compliant properties protocol binding
Browse files Browse the repository at this point in the history
  • Loading branch information
benfrancis committed Sep 22, 2021
1 parent 7a4c641 commit 6ed212a
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 72 deletions.
7 changes: 6 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,12 @@ function createApp(isSecure: boolean): express.Application {
extended: false,
})
);
app.use(bodyParser.json({ limit: '1mb' }));
app.use(
bodyParser.json({
limit: '1mb',
strict: false,
})
);

// Use fileUpload to handle multi-part uploads
app.use(fileUpload());
Expand Down
22 changes: 9 additions & 13 deletions src/controllers/things_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,7 @@ function build(): express.Router {
const propertyName = request.params.propertyName;
try {
const value = await Things.getThingProperty(thingId, propertyName);
const result: Record<string, unknown> = {};
result[propertyName] = value;
response.status(200).json(result);
response.status(200).json(value);
} catch (err) {
response.status(err.code).send(err.message);
}
Expand All @@ -338,20 +336,18 @@ function build(): express.Router {
controller.put('/:thingId/properties/:propertyName', async (request, response) => {
const thingId = request.params.thingId;
const propertyName = request.params.propertyName;
if (!request.body || typeof request.body[propertyName] === 'undefined') {
response.status(400).send('Invalid property name');
if (typeof request.body === 'undefined') {
response.sendStatus(400);
return;
}
const value = request.body[propertyName];
const value = request.body;
try {
// Note: updatedValue may differ from value
const updatedValue = await Things.setThingProperty(thingId, propertyName, value);
const result = {
[propertyName]: updatedValue,
};
response.status(200).json(result);
} catch (e) {
console.error('Error setting property:', e);
response.status(e.code || 500).send(e.message);
response.status(200).json(updatedValue);
} catch (err) {
console.error('Error setting property:', err);
response.status(err.code || 500).send(err.message);
}
});

Expand Down
7 changes: 4 additions & 3 deletions src/test/browser/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export async function getProperty<T>(id: string, property: string): Promise<T> {
.get(`${Constants.THINGS_PATH}/${id}/properties/${property}`)
.set('Accept', 'application/json')
.set(...headerAuth(jwt));
return res.body[property];
return res.body;
}

export async function setProperty<T>(id: string, property: string, value: T): Promise<T> {
Expand All @@ -72,9 +72,10 @@ export async function setProperty<T>(id: string, property: string, value: T): Pr
.keepOpen()
.put(`${Constants.THINGS_PATH}/${id}/properties/${property}`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ [property]: value });
return res.body[property];
.send(JSON.stringify(value));
return res.body;
}

export function escapeHtmlForIdClass(text: string): string {
Expand Down
3 changes: 2 additions & 1 deletion src/test/integration/logs-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ describe('logs/', function () {
.request(server)
.put(`${Constants.THINGS_PATH}/${thingId}/properties/${propId}`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ [propId]: value });
.send(JSON.stringify(value));
expect(res.status).toEqual(200);

// sleep just a bit to allow events to fire in the gateway
Expand Down
84 changes: 42 additions & 42 deletions src/test/integration/things-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,7 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('power');
expect(res.body.power).toEqual(false);
expect(res.body).toEqual(false);
});

it('fail to GET a nonexistent property of a thing', async () => {
Expand Down Expand Up @@ -385,8 +384,9 @@ describe('things/', function () {
.request(server)
.put(`${Constants.THINGS_PATH}/test-1/properties/power`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({});
.send();
expect(err.status).toEqual(400);
});

Expand All @@ -395,8 +395,9 @@ describe('things/', function () {
.request(server)
.put(`${Constants.THINGS_PATH}/test-1/properties/power`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ abc: true });
.send('foo');
expect(err.status).toEqual(400);
});

Expand All @@ -406,24 +407,24 @@ describe('things/', function () {
.request(server)
.put(`${Constants.THINGS_PATH}/test-1/properties/power`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ power: true });
.send(JSON.stringify(true));

expect(on.status).toEqual(200);
expect(on.body).toHaveProperty('power');
expect(on.body.power).toEqual(true);
expect(on.body).toEqual(true);

// Flip it back to off...
const off = await chai
.request(server)
.put(`${Constants.THINGS_PATH}/test-1/properties/power`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ power: false });
.send(JSON.stringify(false));

expect(off.status).toEqual(200);
expect(off.body).toHaveProperty('power');
expect(off.body.power).toEqual(false);
expect(off.body).toEqual(false);
});

it('fail to set x and y coordinates of a non-existent thing', async () => {
Expand Down Expand Up @@ -754,8 +755,9 @@ describe('things/', function () {
.request(server)
.put(`${Constants.THINGS_PATH}/${TEST_THING.id}/properties/power`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ power: true }),
.send(JSON.stringify(true)),
]);
expect(res.status).toEqual(200);
expect(messages[2].messageType).toEqual(Constants.PROPERTY_STATUS);
Expand All @@ -782,8 +784,7 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(on.status).toEqual(200);
expect(on.body).toHaveProperty('power');
expect(on.body.power).toEqual(true);
expect(on.body).toEqual(true);

await webSocketClose(ws);
});
Expand Down Expand Up @@ -865,23 +866,26 @@ describe('things/', function () {
.request(server)
.put(`${Constants.THINGS_PATH}/${otherThingId}/properties/power`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ power: true })
.send(JSON.stringify(true))
.then(() => {
return chai
.request(server)
.put(`${Constants.THINGS_PATH}/${TEST_THING.id}/properties/power`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ power: true });
.send(JSON.stringify(true));
})
.then(() => {
return chai
.request(server)
.put(`${Constants.THINGS_PATH}/${TEST_THING.id}/properties/power`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ power: false });
.send(JSON.stringify(false));
}),
webSocketRead(ws, 4),
]);
Expand Down Expand Up @@ -1445,15 +1449,15 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('readOnlyProp');
expect(res.body.readOnlyProp).toEqual(true);
expect(res.body).toEqual(true);

const err = await chai
.request(server)
.put(`${Constants.THINGS_PATH}/validation-1/properties/readOnlyProp`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ readOnlyProp: false });
.send(JSON.stringify(false));
expect(err.status).toEqual(400);

res = await chai
Expand All @@ -1463,8 +1467,7 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('readOnlyProp');
expect(res.body.readOnlyProp).toEqual(true);
expect(res.body).toEqual(true);
});

it('fail to set invalid number property value', async () => {
Expand All @@ -1477,15 +1480,15 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('minMaxProp');
expect(res.body.minMaxProp).toEqual(15);
expect(res.body).toEqual(15);

let err = await chai
.request(server)
.put(`${Constants.THINGS_PATH}/validation-1/properties/minMaxProp`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ minMaxProp: 0 });
.send(JSON.stringify(0));
expect(err.status).toEqual(400);

res = await chai
Expand All @@ -1495,15 +1498,15 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('minMaxProp');
expect(res.body.minMaxProp).toEqual(15);
expect(res.body).toEqual(15);

err = await chai
.request(server)
.put(`${Constants.THINGS_PATH}/validation-1/properties/minMaxProp`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ minMaxProp: 30 });
.send(JSON.stringify(30));
expect(err.status).toEqual(400);

res = await chai
Expand All @@ -1513,8 +1516,7 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('minMaxProp');
expect(res.body.minMaxProp).toEqual(15);
expect(res.body).toEqual(15);

res = await chai
.request(server)
Expand All @@ -1523,15 +1525,15 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('multipleProp');
expect(res.body.multipleProp).toEqual(10);
expect(res.body).toEqual(10);

err = await chai
.request(server)
.put(`${Constants.THINGS_PATH}/validation-1/properties/multipleProp`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ multipleProp: 3 });
.send(JSON.stringify(3));
expect(err.status).toEqual(400);

res = await chai
Expand All @@ -1541,15 +1543,15 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('multipleProp');
expect(res.body.multipleProp).toEqual(10);
expect(res.body).toEqual(10);

res = await chai
.request(server)
.put(`${Constants.THINGS_PATH}/validation-1/properties/multipleProp`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ multipleProp: 30 });
.send(JSON.stringify(30));
expect(res.status).toEqual(200);

res = await chai
Expand All @@ -1559,8 +1561,7 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('multipleProp');
expect(res.body.multipleProp).toEqual(30);
expect(res.body).toEqual(30);
});

it('fail to set invalid enum property value', async () => {
Expand All @@ -1573,15 +1574,15 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('enumProp');
expect(res.body.enumProp).toEqual('val2');
expect(res.body).toEqual('val2');

const err = await chai
.request(server)
.put(`${Constants.THINGS_PATH}/validation-1/properties/enumProp`)
.set('Accept', 'application/json')
.type('json')
.set(...headerAuth(jwt))
.send({ enumProp: 'val0' });
.send(JSON.stringify('val0'));
expect(err.status).toEqual(400);

res = await chai
Expand All @@ -1591,7 +1592,6 @@ describe('things/', function () {
.set(...headerAuth(jwt));

expect(res.status).toEqual(200);
expect(res.body).toHaveProperty('enumProp');
expect(res.body.enumProp).toEqual('val2');
expect(res.body).toEqual('val2');
});
});
Loading

0 comments on commit 6ed212a

Please sign in to comment.