This repository has been archived by the owner on Aug 9, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* added Cypress tests * Now all typescripted * Improved test to be more clear what is testing when. * Adding logging to help clarrify tests. * First recording will upload * Refactored recording upload * Visits now checked, improved test in runner still timing issues. * First visit tests are complete. * Fixes after Jons review * Beautify run * Travis and readme updated * Travis again. * Excluding cypress ts from api ts build. * Single eslint file. * Eslint uses local packages * Fixed bug with custom tracks not being added Co-authored-by: Clare McLennan <>
- Loading branch information
Showing
30 changed files
with
3,289 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,4 @@ api/**/*.js | |
models/**/*.js | ||
/*.js | ||
dockerstart.log | ||
test-cypress/cypress.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,9 @@ python: | |
install: | ||
- npm install -g [email protected] | ||
- npm run apidoc | ||
- npm install -g eslint | ||
- npm install -g eslint | ||
# global eslint uses local plugins | ||
- npm install eslint-plugin-cypress eslint-plugin-no-only-tests | ||
- sudo apt update | ||
- sudo apt install python3-pip | ||
- sudo apt-get install python3-setuptools | ||
|
@@ -34,6 +36,11 @@ script: | |
- python3 -m pytest --log-api-on-fail | ||
- cd .. | ||
|
||
- cd test-cypress | ||
- cp cypress.json.TEMPLATE cypress.json | ||
- npm install | ||
- npm run release | ||
|
||
before_deploy: | ||
- version=${TRAVIS_TAG/v/} | ||
# Install nfpm tool (for building debs) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Cypress api tests | ||
|
||
## To run the tests on your own machine | ||
To set up the tests on your own machine: | ||
1. Go to the test-cypress folder | ||
2. Copy cypress.json.TEMPLATE to cypress.json. | ||
3. Run | ||
``` bash | ||
npm install | ||
npm run dev | ||
``` | ||
4. Look for the [cypress](https://www.cypress.io/) interactive environment. | ||
|
||
### Testing against a different server | ||
You can test against code running on any environment by changing the cacophony-api-server in cypress.json | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"projectId": "dyez6t", | ||
"env" : { | ||
"cacophony-api-server": "http://localhost:1080", | ||
"testCreds" : {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// load the global Cypress types | ||
/// <reference types="cypress" /> | ||
|
||
declare namespace Cypress { | ||
interface Chainable { | ||
/** | ||
* create a group for the given user (who has already been referenced in the test | ||
*/ | ||
apiCreateCamera( | ||
cameraName: string, | ||
group: string, | ||
log?: boolean | ||
): Chainable<Element>; | ||
|
||
/** | ||
* use to test when a camera should not be able to be created. | ||
*/ | ||
apiShouldFailToCreateCamera( | ||
cameraName: string, | ||
group: string | ||
): Chainable<Element>; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { getTestName } from "../names"; | ||
import { v1ApiPath, saveCreds, checkRequestFails } from "../server"; | ||
import { logTestDescription } from "../descriptions"; | ||
|
||
Cypress.Commands.add( | ||
"apiCreateCamera", | ||
(cameraName: string, group: string, log = true) => { | ||
logTestDescription( | ||
`Create camera '${cameraName}' in group '${group}'`, | ||
{ | ||
camera: cameraName, | ||
group: group | ||
}, | ||
log | ||
); | ||
|
||
const request = createCameraDetails(cameraName, group); | ||
cy.request(request).then((response) => { | ||
const id = response.body.id; | ||
saveCreds(response, cameraName, id); | ||
}); | ||
} | ||
); | ||
|
||
Cypress.Commands.add( | ||
"apiShouldFailToCreateCamera", | ||
(cameraName: string, group: string, log = true) => { | ||
logTestDescription( | ||
`Check that user cannot create camera '${cameraName}' in group '${group}'`, | ||
{ | ||
camera: cameraName, | ||
group: group | ||
}, | ||
log | ||
); | ||
|
||
const request = createCameraDetails(cameraName, group); | ||
checkRequestFails(request); | ||
} | ||
); | ||
|
||
function createCameraDetails( | ||
cameraName: string, | ||
group: string, | ||
shouldFail = false | ||
): any { | ||
const fullName = getTestName(cameraName); | ||
const password = "p" + fullName; | ||
|
||
const data = { | ||
devicename: fullName, | ||
password: password, | ||
group: getTestName(group) | ||
}; | ||
|
||
return { | ||
method: "POST", | ||
url: v1ApiPath("devices"), | ||
body: data | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// load the global Cypress types | ||
/// <reference types="cypress" /> | ||
|
||
interface TrackInfo { | ||
// start_s? : 10, | ||
// end_s? : 22.2, | ||
tag?: string; | ||
// confidence?: number, | ||
} | ||
|
||
interface ThermalRecordingInfo { | ||
time?: Date; | ||
duration?: number; | ||
model?: string; | ||
tracks?: TrackInfo[]; | ||
noTracks?: boolean; // by default there will normally be one track, set to true if you don't want tracks | ||
minsLater?: number; // minutes that later that the recording is taken | ||
secsLater?: number; // minutes that later that the recording is taken | ||
} | ||
|
||
declare namespace Cypress { | ||
interface Chainable { | ||
/** | ||
* upload a single recording to for a particular camera | ||
*/ | ||
uploadRecording( | ||
cameraName: string, | ||
details: ThermalRecordingInfo, | ||
log?: boolean | ||
): Chainable<Element>; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// load the global Cypress types | ||
/// <reference types="cypress" /> | ||
|
||
import { v1ApiPath, uploadFile, DEFAULT_DATE } from "../server"; | ||
import { logTestDescription } from "../descriptions"; | ||
|
||
let lastUsedTime = DEFAULT_DATE; | ||
|
||
Cypress.Commands.add( | ||
"uploadRecording", | ||
(cameraName: string, details: ThermalRecordingInfo, log = true) => { | ||
const data = makeRecordingDataFromDetails(details); | ||
|
||
logTestDescription( | ||
`Upload '${JSON.stringify(details)}' recording to '${cameraName}'`, | ||
{ camera: cameraName, requestData: data }, | ||
log | ||
); | ||
|
||
const fileName = "invalid.cptv"; | ||
const url = v1ApiPath("recordings"); | ||
const fileType = "application/cptv"; | ||
|
||
uploadFile(url, cameraName, fileName, fileType, data); | ||
// must wait until the upload request has completed | ||
cy.wait(["@addRecording"]); | ||
} | ||
); | ||
|
||
type IsoFormattedDateString = string; | ||
|
||
interface TrackData { | ||
start_s?: number; | ||
end_s?: number; | ||
confident_tag?: string; | ||
confidence?: number; | ||
} | ||
|
||
interface AlgorithmMetadata { | ||
model_name?: string; | ||
} | ||
|
||
interface ThermalRecordingMetaData { | ||
algorithm?: AlgorithmMetadata; | ||
tracks: TrackData[]; | ||
} | ||
|
||
interface ThermalRecordingData { | ||
type: "thermalRaw"; | ||
recordingDateTime: IsoFormattedDateString; | ||
duration: number; | ||
comment?: string; | ||
batteryLevel?: number; | ||
batteryCharging?: string; | ||
airplaneModeOn?: boolean; | ||
version?: string; | ||
additionalMetadata?: JSON; | ||
metadata?: ThermalRecordingMetaData; | ||
} | ||
|
||
function makeRecordingDataFromDetails( | ||
details: ThermalRecordingInfo | ||
): ThermalRecordingData { | ||
let data: ThermalRecordingData = { | ||
type: "thermalRaw", | ||
recordingDateTime: "", | ||
duration: 12, | ||
comment: "uploaded by cypress" | ||
}; | ||
|
||
if (details.duration) { | ||
data.duration = details.duration; | ||
} | ||
|
||
data.recordingDateTime = getDateForRecordings(details).toISOString(); | ||
|
||
if (!details.noTracks) { | ||
const model = details.model ? details.model : "Master"; | ||
addTracksToRecording(data, model, details.tracks); | ||
} | ||
|
||
return data; | ||
} | ||
|
||
function getDateForRecordings(details: ThermalRecordingInfo): Date { | ||
let date = lastUsedTime; | ||
|
||
if (details.time) { | ||
date = details.time; | ||
} else if (details.minsLater || details.secsLater) { | ||
let secs = 0; | ||
if (details.minsLater) { | ||
secs += details.minsLater * 60; | ||
} | ||
if (details.secsLater) { | ||
secs += details.secsLater; | ||
} | ||
date = new Date(date.getTime() + secs * 1000); | ||
} else { | ||
// add a minute anyway so we don't get two overlapping recordings on the same camera | ||
const MINUTE = 60; | ||
date = new Date(date.getTime() + MINUTE * 1000); | ||
} | ||
|
||
lastUsedTime = date; | ||
return date; | ||
} | ||
|
||
function addTracksToRecording( | ||
data: ThermalRecordingData, | ||
model: string, | ||
trackDetails?: TrackInfo[] | ||
): void { | ||
data.metadata = { | ||
algorithm: { | ||
model_name: model | ||
}, | ||
tracks: [] | ||
}; | ||
|
||
if (trackDetails) { | ||
data.metadata.tracks = trackDetails.map((track) => { | ||
let tag = track.tag ? track.tag : "possum"; | ||
return { | ||
start_s: 2, | ||
end_s: 8, | ||
confident_tag: tag, | ||
confidence: 0.9 | ||
}; | ||
}); | ||
} else { | ||
data.metadata.tracks.push({ | ||
start_s: 2, | ||
end_s: 8, | ||
confident_tag: "possum", | ||
confidence: 0.5 | ||
}); | ||
} | ||
} |
Oops, something went wrong.