Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add type json-schemas for all data models #124

Merged
merged 16 commits into from
Aug 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ cp cobuy-config/*.js cobuy/config
heroku run npm run db migrate:latest --app=cobuy
```

### JSON schema
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 yay docs 📔


All models must have an assoicated JSON schema. See [#118](https://github.com/root-systems/cobuy/issues/118) for more info.

We're using [json-schema-faker](https://github.com/json-schema-faker/json-schema-faker/#faking-values) to fake data for tests and storybook.

### How to [storybook](https://storybook.js.org)

So you want to tell a story about dumb React components, ey?
Expand Down
35 changes: 35 additions & 0 deletions agents/schemas/profile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"$schema": "http://json-schema.org/schema#",
"id": "agents/Profile",
"title": "Profile",
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Id referencing profile"
},
"agentId": {
"type": "integer",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be

{
  "$ref": "/agents/Agent#/definitions/id"
}

oh wait nevermind, we don't have a schema for Agent. all good!

"description": "Id referencing agent"
},
"name": {
"type": "string",
"faker": "name.findName",
"description": "An agent name"
},
"description": {
"type": "string",
"description": "Agent biography"
},
"avatar" : {
"type": "string",
"faker": "internet.avatar",
"format": "uri",
"description": "Agent avatar image link"
}
},
"required": [
"id",
"agentId"
]
}
16 changes: 8 additions & 8 deletions agents/stories/Profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import React from 'react'
import { storiesOf } from '@storybook/react'
import { action } from '@storybook/addon-actions'
import { reduxForm, Field } from 'redux-form'
import h from 'react-hyperscript'
import jsf from 'json-schema-faker'

import schema from '../schemas/profile'
import Profile from '../components/Profile'

const alice = {
profile: {
name: 'Alice',
description: 'a cool cat',
avatar: 'http://dinosaur.is/images/mikey-small.jpg'
}
}
const profile = jsf(schema)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fk ya


storiesOf('agents.Profile', module)
.add('basic', () => (
<Profile agent={alice} />
h(Profile, {
initialValues: profile
})
))
11 changes: 11 additions & 0 deletions app/schemas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const Ajv = require('ajv')
const ajv = new Ajv()

const taskPlanSchema = require('../tasks/schemas/taskPlan')
const taskRecipeSchema = require('../tasks/schemas/taskRecipe')
ajv.addSchema([
taskRecipeSchema,
taskPlanSchema
])

export default ajv
4 changes: 2 additions & 2 deletions ordering/services/orders.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ function createPrereqTaskPlan (hook) {
// const assigneeId = hook.params.agent.id

const assigneeId = hook.params.credential.agentId
const params = JSON.stringify({
const params = {
contextAgentId: hook.data.agentId
})
}
return taskPlans.create({ taskRecipeId, params, assigneeId })
.then(() => {
return hook
Expand Down
29 changes: 26 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@ahdinosaur/react-fela": "^4.3.5",
"@f/create-action": "^1.1.1",
"@root-systems/redux-form-validators": "^1.1.0",
"ajv": "^5.2.2",
"babel-plugin-ramda": "^1.2.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
Expand Down Expand Up @@ -108,6 +109,7 @@
"dependency-check": "^2.8.0",
"maildev": "^1.0.0-rc3",
"npm-run-all": "^4.0.2",
"json-schema-faker": "^0.4.3",
"precinct": "^3.6.0",
"sqlite3": "3.1.8"
}
Expand Down
6 changes: 3 additions & 3 deletions tasks/data/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const mockEnhancedTaskPlans = {
taskRecipeId: 'finishPrereqs',
taskRecipe: finishPrereqs,
params: {
contextAgent: group
contextAgentId: group.id
}
},
2: {
Expand All @@ -100,7 +100,7 @@ export const mockEnhancedTaskPlans = {
taskRecipeId: 'setupGroup',
taskRecipe: setupGroup,
params: {
contextAgent: group
contextAgentId: group.id
}
},
3: {
Expand All @@ -110,7 +110,7 @@ export const mockEnhancedTaskPlans = {
taskRecipeId: 'setupSupplier',
taskRecipe: setupSupplier,
params: {
contextAgent: group
contextAgentId: group.id
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions tasks/schemas/taskPlan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"id": "/tasks/taskPlan",
"title": "Task Plan",
"description": "An assignment of the task to an agent",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! thanks you.

"type": "object",
"properties": {
"id": {
"$ref": "#/definitions/id"
},
"parentTaskPlanID": {
"$ref": "#/definitions/id"
},
"assigneeId": {
"type": "integer",
"description": "Person or group or related agents (e.g. admins) being assigned"
},
"taskRecipeId": {
"$ref": "/tasks/taskRecipe#/definitions/id",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweet. 🍈

"description": "Task recipe that this taask plan is related to"
},
"params": {
"type": "object",
"description": "Util paramaters"
}
},
"required": [
"assigneeId",
"taskRecipeId"
],
"definitions": {
"id": {
"type": "integer",
"description": "Id referencing task plan"
}
}
}
36 changes: 36 additions & 0 deletions tasks/schemas/taskRecipe.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"id": "/tasks/taskRecipe",
"title": "Task Recipe",
"description": "An abstract description of the task",
"type": "object",
"properties": {
"id": {
"$ref": "#/definitions/id"
},
"ownerAgentId": {
"type": "integer",
"description": "Id of the agent that owns the recipe"
},
"childTaskRecipes": {
"type": "array",
"items": [
{
"$ref": "#"
}
],
"description": "Task recipes that make up this task recipe..."
}
},
"definitions": {
"id": {
"enum": [
"setupGroup",
"setupSupplier",
"finishPrereqs"
]
}
},
"required": [
"id"
]
}
22 changes: 16 additions & 6 deletions tasks/services/plans.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const feathersKnex = require('feathers-knex')
const { iff } = require('feathers-hooks-common')
import { isEmpty, ifElse, is, assoc, prop, map, pipe, __ } from 'ramda'
const { iff, validateSchema } = require('feathers-hooks-common')
const taskPlanSchema = require('../schemas/taskPlan')
import ajv from '../../app/schemas'
import * as taskRecipes from '../../tasks/data/recipes'

module.exports = function () {
Expand All @@ -16,8 +18,17 @@ module.exports = function () {

const hooks = {
before: {
all: [
// encodeParams
create: [
validateSchema(taskPlanSchema, ajv),
encodeParams
],
update: [
validateSchema(taskPlanSchema, ajv),
encodeParams
],
patch: [
validateSchema(taskPlanSchema, ajv),
encodeParams
]
},
after: {
Expand Down Expand Up @@ -46,11 +57,11 @@ function createChildTaskPlans (hook) {
parentTaskPlanId: hook.result.id,
assigneeId: hook.data.assigneeId,
taskRecipeId: childTaskRecipe.id,
params: hook.data.params
params: hook.result.params
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch

})
})
)
.then(() => hook)
.then(() => hook)
}

const transformProp = transformer => propName => object => pipe(
Expand All @@ -77,5 +88,4 @@ function decodeParams (hook) {
if (hook.result) {
hook.result = transformPropMaybeArray(JSON.parse)('params')(hook.result)
}
return hook
}
30 changes: 30 additions & 0 deletions tasks/util/validateTaskPlan.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import test from 'ava'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woo hoo tests 😊

import * as mock from '../data/mock'
import ajv from '../../app/schemas'

const { validateSchema } = require('feathers-hooks-common')
const schema = require('../schemas/taskPlan')

let hookBefore

test.beforeEach(t => {
hookBefore = {
type: 'before',
method: 'create',
params: { provider: 'rest' },
data: mock.mockTaskPlans[1]
}
console.log(hookBefore.data)
})

test('works with simple plan', (t) => {
try {
validateSchema(schema, ajv)(hookBefore)
} catch (err) {
if (err.errors) {
console.log('validation errors: ', err.errors)
}
t.fail('validation failed unexpectedly')
}
t.pass('recipe was validated')
})
Loading