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

Observe API service #119

Merged
merged 25 commits into from
Nov 14, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
16924c4
[wip] service to talk to the observe api
batpad Oct 29, 2019
e30c94a
use qs module instead of custom util function to stringify querystring
batpad Oct 30, 2019
6d2fdcf
lintfixes
batpad Oct 30, 2019
8a400ea
[wip] start scaffolding action to upload all traces, api call + add e…
batpad Oct 31, 2019
da26185
actions for start upload trace / uploaded trace / trace upload error
batpad Oct 31, 2019
b8745cc
[wip] reducers to trace upload actions
batpad Nov 4, 2019
4977533
call uploadPendingTraces action
batpad Nov 4, 2019
77a0e9a
[wip] posting to API works
batpad Nov 4, 2019
1bbbfa5
dont try and upload a trace that is in an uploading state
batpad Nov 5, 2019
a02e72d
add persistence for observe api token
batpad Nov 5, 2019
a8c55be
[wip] start adding tests for trace upload actions
batpad Nov 5, 2019
72b14d5
lintfix
batpad Nov 5, 2019
24af884
add tests to handle pending and uploading states of traces
batpad Nov 5, 2019
ba3b059
add basic test that error fires error action and stores error details…
batpad Nov 5, 2019
6993c65
lintfix
batpad Nov 5, 2019
e6bac50
Merge branch 'develop' into feature/observe-api-service
sethvincent Nov 7, 2019
a4eccc1
add example env to .env.sample, add storage to observeApiPersistConfig
sethvincent Nov 7, 2019
9e1599d
check if properties obj exists on new traces
sethvincent Nov 8, 2019
956105c
[wip] reducer tests
batpad Nov 11, 2019
65799fd
Merge branch 'feature/observe-api-service' of github.com:developments…
batpad Nov 11, 2019
db2a412
test for trace upload failed reducer
batpad Nov 13, 2019
591248f
use status string to signify pending, uploading, uploaded for traces,…
batpad Nov 13, 2019
d00958d
Merge branch 'develop' into feature/observe-api-service
geohacker Nov 14, 2019
4bca657
merge develop
geohacker Nov 14, 2019
a1589a2
Merge branch 'feature/observe-api-service' of github.com:developments…
geohacker Nov 14, 2019
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
9 changes: 6 additions & 3 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@ OAUTH_CONSUMER_KEY=<consumer_key>
OAUTH_CONSUMER_SECRET=<consumer_secret>

# require additional auth before osm auth
PREAUTH_URL=<optional>
PREAUTH_NAME=<optional>
# PREAUTH_URL=<optional>
# PREAUTH_NAME=<optional>

# geocoding via opencage
OPENCAGE_KEY=<optional>

# set limit for downloading mapbox tiles. 6000 is default and compliant with ToS
MAPBOX_OFFLINE_TILE_DOWNLOAD_LIMIT=6000
MAPBOX_OFFLINE_TILE_DOWNLOAD_LIMIT=6000

# optional observe api endpoint to send photos and traces to
# OBSERVE_API_URL=<optional>
172 changes: 171 additions & 1 deletion __tests__/actions/__snapshots__/trace.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`test trace actions should start trace correctly 1`] = `
exports[`test trace sync actions should start trace correctly 1`] = `
Array [
Object {
"type": "TRACE_START",
Expand Down Expand Up @@ -45,3 +45,173 @@ Array [
},
]
`;

exports[`trace upload / async actions should add error to the trace for an error response 1`] = `
Array [
Object {
"id": "id-1",
"type": "TRACE_UPLOAD_STARTED",
},
Object {
"error": [Error: Unknown error],
"id": "id-1",
"type": "TRACE_UPLOAD_FAILED",
},
]
`;

exports[`trace upload / async actions should add error to the trace for an error response 2`] = `
Array [
Array [
"http://localhost:3000/traces",
Object {
"body": "{\\"tracejson\\":{\\"type\\":\\"Feature\\",\\"properties\\":{\\"timestamps\\":[1,11,21],\\"description\\":\\"\\"},\\"geometry\\":{\\"type\\":\\"LineString\\",\\"coordinates\\":[[1,1],[2,0],[3,-1]]}}}",
"headers": Object {
"Authorization": "abcd",
"Content-Type": "application/json",
},
"method": "POST",
},
],
]
`;

exports[`trace upload / async actions should not upload non-pending traces 1`] = `
Array [
Object {
"id": "id-1",
"type": "TRACE_UPLOAD_STARTED",
},
Object {
"newId": "fakeid-1",
"oldId": "id-1",
"type": "TRACE_UPLOADED",
},
]
`;

exports[`trace upload / async actions should not upload non-pending traces 2`] = `
Array [
Array [
"http://localhost:3000/traces",
Object {
"body": "{\\"tracejson\\":{\\"type\\":\\"Feature\\",\\"properties\\":{\\"timestamps\\":[1,11,21],\\"description\\":\\"\\"},\\"geometry\\":{\\"type\\":\\"LineString\\",\\"coordinates\\":[[1,1],[2,0],[3,-1]]}}}",
"headers": Object {
"Authorization": "abcd",
"Content-Type": "application/json",
},
"method": "POST",
},
],
]
`;

exports[`trace upload / async actions should not upload uploading traces 1`] = `
Array [
Object {
"id": "id-2",
"type": "TRACE_UPLOAD_STARTED",
},
Object {
"newId": "fakeid-2",
"oldId": "id-2",
"type": "TRACE_UPLOADED",
},
]
`;

exports[`trace upload / async actions should not upload uploading traces 2`] = `
Array [
Array [
"http://localhost:3000/traces",
Object {
"body": "{\\"tracejson\\":{\\"type\\":\\"Feature\\",\\"properties\\":{\\"timestamps\\":[2,12,22],\\"description\\":\\"\\"},\\"geometry\\":{\\"type\\":\\"LineString\\",\\"coordinates\\":[[2,2],[3,1],[4,0]]}}}",
"headers": Object {
"Authorization": "abcd",
"Content-Type": "application/json",
},
"method": "POST",
},
],
]
`;

exports[`trace upload / async actions should upload a single trace 1`] = `
Array [
Object {
"id": "id-1",
"type": "TRACE_UPLOAD_STARTED",
},
Object {
"newId": "fakeid",
"oldId": "id-1",
"type": "TRACE_UPLOADED",
},
]
`;

exports[`trace upload / async actions should upload a single trace 2`] = `
Array [
Array [
"http://localhost:3000/traces",
Object {
"body": "{\\"tracejson\\":{\\"type\\":\\"Feature\\",\\"properties\\":{\\"timestamps\\":[1,11,21],\\"description\\":\\"\\"},\\"geometry\\":{\\"type\\":\\"LineString\\",\\"coordinates\\":[[1,1],[2,0],[3,-1]]}}}",
"headers": Object {
"Authorization": "abcd",
"Content-Type": "application/json",
},
"method": "POST",
},
],
]
`;

exports[`trace upload / async actions should upload multiple pending traces 1`] = `
Array [
Object {
"id": "id-1",
"type": "TRACE_UPLOAD_STARTED",
},
Object {
"newId": "fakeid-1",
"oldId": "id-1",
"type": "TRACE_UPLOADED",
},
Object {
"id": "id-2",
"type": "TRACE_UPLOAD_STARTED",
},
Object {
"newId": "fakeid-2",
"oldId": "id-2",
"type": "TRACE_UPLOADED",
},
]
`;

exports[`trace upload / async actions should upload multiple pending traces 2`] = `
Array [
Array [
"http://localhost:3000/traces",
Object {
"body": "{\\"tracejson\\":{\\"type\\":\\"Feature\\",\\"properties\\":{\\"timestamps\\":[1,11,21],\\"description\\":\\"\\"},\\"geometry\\":{\\"type\\":\\"LineString\\",\\"coordinates\\":[[1,1],[2,0],[3,-1]]}}}",
"headers": Object {
"Authorization": "abcd",
"Content-Type": "application/json",
},
"method": "POST",
},
],
Array [
"http://localhost:3000/traces",
Object {
"body": "{\\"tracejson\\":{\\"type\\":\\"Feature\\",\\"properties\\":{\\"timestamps\\":[2,12,22],\\"description\\":\\"\\"},\\"geometry\\":{\\"type\\":\\"LineString\\",\\"coordinates\\":[[2,2],[3,1],[4,0]]}}}",
"headers": Object {
"Authorization": "abcd",
"Content-Type": "application/json",
},
"method": "POST",
},
],
]
`;
168 changes: 165 additions & 3 deletions __tests__/actions/trace.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global jest, it, expect, describe */
/* global jest, it, expect, describe, fetch */

import configureStore from 'redux-mock-store'
import thunk from 'redux-thunk'
Expand All @@ -8,7 +8,8 @@ import {
pauseTrace,
unpauseTrace,
startSavingTrace,
discardTrace
discardTrace,
uploadPendingTraces
} from '../../app/actions/traces'
const middlewares = [thunk]
const mockStore = configureStore(middlewares)
Expand Down Expand Up @@ -45,6 +46,22 @@ jest.mock('../../app/services/trace', () => {
}
})

// This is required because the observe API service calls the store directly
// to get the token.
jest.mock('../../app/utils/store', () => {
return {
store: {
getState: () => {
return {
observeApi: {
token: 'abcd'
}
}
}
}
}
})

const getMockCurrentTrace = function () {
return {
type: 'Feature',
Expand All @@ -59,7 +76,59 @@ const getMockCurrentTrace = function () {
}
}

describe('test trace actions', () => {
/**
*
* @param {Number} m - used to construct id, timestamps, coords
*/
const getMockTrace = function (m) {
return {
id: `id-${m}`,
pending: true,
uploading: false,
geojson: {
type: 'Feature',
properties: {
timestamps: [
m,
m + 10,
m + 20
]
},
geometry: {
type: 'LineString',
coordinates: [
[m, m],
[m + 1, m - 1],
[m + 2, m - 2]
]
}
}
}
}

const getMockTracePostResponse = function (m, id) {
return {
type: 'Feature',
properties: {
id,
timestamps: [
m,
m + 10,
m + 20
]
},
geometry: {
type: 'LineString',
coordinates: [
[m, m],
[m + 1, m - 1],
[m + 2, m - 2]
]
}
}
}

describe('test trace sync actions', () => {
it('should start trace correctly', () => {
const store = mockStore({
traces: {
Expand Down Expand Up @@ -123,3 +192,96 @@ describe('test trace actions', () => {
expect(actions[0].type).toEqual('TRACE_DISCARD')
})
})

describe('trace upload / async actions', () => {
it('should upload a single trace', async () => {
const store = mockStore({
traces: {
traces: [
getMockTrace(1)
]
}
})
fetch.resetMocks()
fetch.once(JSON.stringify(getMockTracePostResponse(1, 'fakeid')))
await store.dispatch(uploadPendingTraces())
const actions = store.getActions()
expect(actions).toMatchSnapshot()
expect(fetch.mock.calls).toMatchSnapshot()
})

it('should upload multiple pending traces', async () => {
const store = mockStore({
traces: {
traces: [
getMockTrace(1),
getMockTrace(2)
]
}
})
fetch.resetMocks()
fetch.once(JSON.stringify(getMockTracePostResponse(1, 'fakeid-1')))
.once(JSON.stringify(getMockTracePostResponse(2, 'fakeid-2')))
await store.dispatch(uploadPendingTraces())
const actions = store.getActions()
expect(actions).toMatchSnapshot()
expect(fetch.mock.calls).toMatchSnapshot()
})

it('should not upload non-pending traces', async () => {
const trace1 = getMockTrace(1)
const trace2 = getMockTrace(2)
trace2.pending = false
const store = mockStore({
traces: {
traces: [
trace1,
trace2
]
}
})
fetch.resetMocks()
fetch.once(JSON.stringify(getMockTracePostResponse(1, 'fakeid-1')))
await store.dispatch(uploadPendingTraces())
const actions = store.getActions()
expect(actions).toMatchSnapshot()
expect(fetch.mock.calls).toMatchSnapshot()
})

it('should not upload uploading traces', async () => {
const trace1 = getMockTrace(1)
trace1.uploading = true
const trace2 = getMockTrace(2)
const store = mockStore({
traces: {
traces: [
trace1,
trace2
]
}
})
fetch.resetMocks()
fetch.once(JSON.stringify(getMockTracePostResponse(2, 'fakeid-2')))
await store.dispatch(uploadPendingTraces())
const actions = store.getActions()
expect(actions).toMatchSnapshot()
expect(fetch.mock.calls).toMatchSnapshot()
})

it('should add error to the trace for an error response', async () => {
const trace1 = getMockTrace(1)
const store = mockStore({
traces: {
traces: [
trace1
]
}
})
fetch.resetMocks()
fetch.once(JSON.stringify({ 'message': 'Unknown error' }), { status: 500 })
await store.dispatch(uploadPendingTraces())
const actions = store.getActions()
expect(actions).toMatchSnapshot()
expect(fetch.mock.calls).toMatchSnapshot()
})
})
Loading