mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Refactor tests & add create & delete tests for species
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"dev": "npx tsx watch --clear-screen=false src/index.ts",
|
||||
"build": "tsc",
|
||||
"test": "node --import tsx --test src/api-tests/**/*.ts",
|
||||
"test": "node --import tsx --test src/api-tests/**/*test.ts",
|
||||
"start": "node build/index.js",
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"prisma": "prisma generate --schema prisma/schema.prisma && prisma generate --schema prisma/schema_log.prisma"
|
||||
|
||||
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict'
|
||||
import { before, describe, it } from 'node:test'
|
||||
import { LocalityDetailsType, SpeciesDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
import { LogRow } from '../../services/writeOperations/types'
|
||||
import { newLocalityBasis } from '../data'
|
||||
import { newLocalityBasis } from './data'
|
||||
import { login, send, testLogRows } from '../utils'
|
||||
|
||||
let createdLocality: LocalityDetailsType | null = null
|
||||
@@ -35,7 +35,8 @@ describe('Creating new locality works', () => {
|
||||
it('Species update also logged correctly', async () => {
|
||||
const speciesId = createdLocality!.now_ls.find(ls => ls.com_species.species_name === 'Newspecies')?.species_id
|
||||
const speciesResult = await send<SpeciesDetailsType>(`species/${speciesId}`, 'GET')
|
||||
const update = speciesResult.body.now_sau[0]
|
||||
const update = speciesResult.body.now_sau.find(update => update.sau_comment === 'new locality test update')
|
||||
assert(update, 'Species update not found')
|
||||
update.species_id === speciesId
|
||||
const logRows = update.updates
|
||||
const expectedLogRows: Partial<LogRow>[] = [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Reference, SpeciesDetailsType } from '../../../frontend/src/backendTypes'
|
||||
import { Reference, SpeciesDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
|
||||
export const newLocalityBasis = {
|
||||
bfa_max: 'bahean',
|
||||
@@ -175,6 +175,7 @@ export const newLocalityBasis = {
|
||||
rowState: 'new',
|
||||
},
|
||||
],
|
||||
comment: 'new locality test update',
|
||||
}
|
||||
|
||||
export const editedLocality = {
|
||||
@@ -2,7 +2,6 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { describe, it, before } from 'node:test'
|
||||
import { login, send } from '../utils'
|
||||
import { LocalityDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
|
||||
describe('Deleting a locality works', async () => {
|
||||
before(async () => {
|
||||
@@ -11,7 +10,7 @@ describe('Deleting a locality works', async () => {
|
||||
await it('Deleting works', async () => {
|
||||
const deleteResult = await send<{ id: number }>('locality/28518', 'DELETE')
|
||||
assert(deleteResult.status === 200)
|
||||
const getResult = await send<LocalityDetailsType>('locality/28518', 'GET')
|
||||
assert(getResult.status === 404, 'Locality status was not 404 after deletion')
|
||||
const getResult = await send('locality/28518', 'GET')
|
||||
assert(getResult.status === 404, 'Locality response status was not 404 after deletion')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict'
|
||||
import { before, describe, it } from 'node:test'
|
||||
import { LocalityDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
import { LogRow } from '../../services/writeOperations/types'
|
||||
import { editedLocality } from '../data'
|
||||
import { editedLocality } from './data'
|
||||
import { login, send, testLogRows } from '../utils'
|
||||
|
||||
let resultLocality: LocalityDetailsType | null = null
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import assert from 'node:assert/strict'
|
||||
import { before, describe, it } from 'node:test'
|
||||
import { LocalityDetailsType, SpeciesDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
import { LogRow } from '../../services/writeOperations/types'
|
||||
import { newSpeciesBasis } from './data'
|
||||
import { login, send, testLogRows } from '../utils'
|
||||
|
||||
let createdSpecies: SpeciesDetailsType | null = null
|
||||
|
||||
describe.only('Creating new species works', () => {
|
||||
before(async () => {
|
||||
await login()
|
||||
})
|
||||
|
||||
it('Request succeeds and returns valid number id', async () => {
|
||||
const { body: resultBody } = await send<{ id: number }>('species', 'PUT', {
|
||||
species: { ...newSpeciesBasis, comment: 'species test' },
|
||||
})
|
||||
const { id: createdId } = resultBody
|
||||
|
||||
assert(typeof createdId === 'number', `Invalid result returned on write: ${createdId}`)
|
||||
|
||||
const { body } = await send<SpeciesDetailsType>(`species/${createdId}`, 'GET')
|
||||
createdSpecies = body
|
||||
})
|
||||
|
||||
it('Contains correct data', () => {
|
||||
const { species_name, now_ls } = createdSpecies!
|
||||
assert(species_name === newSpeciesBasis.species_name, 'Name is different')
|
||||
const locality = now_ls.find(ls => ls.now_loc.lid === 24750)
|
||||
assert(!!locality, 'Locality in locality-species not found')
|
||||
})
|
||||
|
||||
it('Locality-species change was updated also to locality', async () => {
|
||||
const localityFound = createdSpecies!.now_ls.find(ls => ls.now_loc.loc_name.startsWith('Romany'))
|
||||
assert(localityFound, 'Locality was not found in now_ls')
|
||||
const speciesResult = await send<LocalityDetailsType>(`locality/24750`, 'GET')
|
||||
const update = speciesResult.body.now_lau.find(lau => lau.lid === 24750 && lau.lau_comment === 'species test')
|
||||
assert(update, 'Update not found')
|
||||
const logRows = update.updates
|
||||
const expectedLogRows: Partial<LogRow>[] = [
|
||||
{
|
||||
oldValue: null,
|
||||
value: '24750',
|
||||
type: 'add',
|
||||
column: 'lid',
|
||||
table: 'now_ls',
|
||||
},
|
||||
]
|
||||
testLogRows(logRows, expectedLogRows, 2)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,107 @@
|
||||
import { EditDataType, SpeciesDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
|
||||
export const newSpeciesBasis: EditDataType<SpeciesDetailsType> = {
|
||||
class_name: 'Mammalia',
|
||||
order_name: 'Eulipotyphla',
|
||||
family_name: 'Soricidae',
|
||||
subclass_or_superorder_name: 'Eutheria',
|
||||
suborder_or_superfamily_name: null,
|
||||
subfamily_name: 'Soricinae',
|
||||
genus_name: 'Petenyia',
|
||||
species_name: 'dubia test',
|
||||
unique_identifier: '-',
|
||||
taxonomic_status: null,
|
||||
common_name: null,
|
||||
sp_author: 'Bachmayer & Wilson, 1970',
|
||||
strain: null,
|
||||
gene: null,
|
||||
taxon_status: null,
|
||||
diet1: 'a',
|
||||
diet2: null,
|
||||
diet3: null,
|
||||
diet_description: null,
|
||||
rel_fib: null,
|
||||
selectivity: null,
|
||||
digestion: null,
|
||||
feedinghab1: null,
|
||||
feedinghab2: null,
|
||||
shelterhab1: null,
|
||||
shelterhab2: null,
|
||||
locomo1: null,
|
||||
locomo2: null,
|
||||
locomo3: null,
|
||||
hunt_forage: null,
|
||||
brain_mass: null,
|
||||
sv_length: null,
|
||||
activity: null,
|
||||
sd_size: null,
|
||||
sd_display: null,
|
||||
tshm: null,
|
||||
symph_mob: null,
|
||||
relative_blade_length: null,
|
||||
tht: null,
|
||||
crowntype: null,
|
||||
microwear: null,
|
||||
horizodonty: null,
|
||||
cusp_shape: null,
|
||||
cusp_count_buccal: null,
|
||||
cusp_count_lingual: null,
|
||||
loph_count_lon: null,
|
||||
loph_count_trs: null,
|
||||
fct_al: null,
|
||||
fct_ol: null,
|
||||
fct_sf: null,
|
||||
fct_ot: null,
|
||||
fct_cm: null,
|
||||
mesowear: null,
|
||||
mw_or_high: null,
|
||||
mw_or_low: null,
|
||||
mw_cs_sharp: null,
|
||||
mw_cs_round: null,
|
||||
mw_cs_blunt: null,
|
||||
mw_scale_min: null,
|
||||
mw_scale_max: null,
|
||||
mw_value: null,
|
||||
pop_struc: null,
|
||||
sp_status: false,
|
||||
used_morph: null,
|
||||
used_now: true,
|
||||
used_gene: null,
|
||||
sp_comment: null,
|
||||
now_ls: [
|
||||
{
|
||||
rowState: 'new',
|
||||
lid: 24750,
|
||||
nis: null,
|
||||
pct: null,
|
||||
quad: null,
|
||||
mni: null,
|
||||
qua: null,
|
||||
id_status: null,
|
||||
orig_entry: null,
|
||||
source_name: null,
|
||||
mesowear: null,
|
||||
mw_or_high: null,
|
||||
mw_or_low: null,
|
||||
mw_cs_sharp: null,
|
||||
mw_cs_round: null,
|
||||
mw_cs_blunt: null,
|
||||
mw_scale_min: null,
|
||||
mw_scale_max: null,
|
||||
mw_value: null,
|
||||
microwear: null,
|
||||
dc13_mean: null,
|
||||
dc13_n: null,
|
||||
dc13_max: null,
|
||||
dc13_min: null,
|
||||
dc13_stdev: null,
|
||||
do18_mean: null,
|
||||
do18_n: null,
|
||||
do18_max: null,
|
||||
do18_min: null,
|
||||
do18_stdev: null,
|
||||
},
|
||||
],
|
||||
now_sau: [],
|
||||
com_taxa_synonym: [],
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import assert from 'node:assert/strict'
|
||||
import { describe, it, before } from 'node:test'
|
||||
import { login, send } from '../utils'
|
||||
|
||||
describe('Deleting a species works', async () => {
|
||||
before(async () => {
|
||||
await login()
|
||||
})
|
||||
await it('Deleting returns correct status and after that is not found on request', async () => {
|
||||
const deleteResult = await send<{ id: number }>('species/84357', 'DELETE')
|
||||
assert(deleteResult.status === 200)
|
||||
const getResult = await send('species/84357', 'GET')
|
||||
assert(getResult.status === 404, 'Species response status was not 404 after deletion')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,74 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import assert from 'node:assert/strict'
|
||||
import { before, describe, it } from 'node:test'
|
||||
import { LocalityDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
import { LogRow } from '../../services/writeOperations/types'
|
||||
import { editedLocality } from '../locality/data'
|
||||
import { login, send, testLogRows } from '../utils'
|
||||
|
||||
let resultLocality: LocalityDetailsType | null = null
|
||||
|
||||
describe('Locality write works', () => {
|
||||
before(async () => {
|
||||
await login()
|
||||
})
|
||||
|
||||
it('Edits name, synonyms and locality species correctly', async () => {
|
||||
const writeResult = await send<{ id: number }>('locality', 'PUT', { locality: editedLocality })
|
||||
|
||||
assert(writeResult.body.id === editedLocality.lid, `Invalid result returned on write: ${writeResult.body.id}`)
|
||||
|
||||
const { body } = await send<LocalityDetailsType>(`locality/${editedLocality.lid}`, 'GET')
|
||||
resultLocality = body
|
||||
})
|
||||
|
||||
it('Name changed correctly', () => {
|
||||
assert(resultLocality!.loc_name === editedLocality.loc_name, 'Name was not changed correctly')
|
||||
})
|
||||
|
||||
it('Added locality species is found', () => {
|
||||
assert(
|
||||
resultLocality!.now_ls.find(ls => ls.species_id === 21052 && ls.lid === 21050),
|
||||
'Added locality species not found'
|
||||
)
|
||||
})
|
||||
|
||||
it('Locality species include exactly two entries', () => {
|
||||
assert(resultLocality!.now_ls.length === 2, `Unexpected now_ls length: ${resultLocality!.now_ls.length}`)
|
||||
})
|
||||
|
||||
it('Changes were logged correctly', () => {
|
||||
const update = resultLocality!.now_lau
|
||||
const lastUpdate = update[update.length - 1]
|
||||
|
||||
assert(lastUpdate.lau_comment === editedLocality.comment, 'Comment wrong')
|
||||
assert(lastUpdate.now_lr[lastUpdate.now_lr.length - 1].rid === editedLocality.references[0].rid)
|
||||
|
||||
const logRows = lastUpdate.updates
|
||||
|
||||
const expectedLogRows: Partial<LogRow>[] = [
|
||||
{
|
||||
oldValue: 'Dmanisi',
|
||||
value: editedLocality.loc_name,
|
||||
type: 'update',
|
||||
column: 'loc_name',
|
||||
table: 'now_loc',
|
||||
},
|
||||
{
|
||||
oldValue: '21050',
|
||||
value: null,
|
||||
type: 'delete',
|
||||
column: 'lid',
|
||||
table: 'now_ls',
|
||||
},
|
||||
{
|
||||
oldValue: '85729',
|
||||
value: null,
|
||||
type: 'delete',
|
||||
column: 'species_id',
|
||||
table: 'now_ls',
|
||||
},
|
||||
]
|
||||
testLogRows(logRows, expectedLogRows, 5)
|
||||
})
|
||||
})
|
||||
@@ -15,6 +15,7 @@ export const send = async <T extends Record<string, unknown>>(
|
||||
if (token) headers.append('authorization', `bearer ${token}`)
|
||||
const options = { body: method !== 'GET' ? JSON.stringify(body) : undefined, method, headers }
|
||||
const response = await fetch(`${baseUrl}/${path}`, options)
|
||||
if (response.status > 399) return { body: {} as T, status: response.status }
|
||||
const responseText = await response.text()
|
||||
if (!responseText) return { body: {} as T, status: response.status }
|
||||
return { body: JSON.parse(responseText) as T, status: response.status }
|
||||
@@ -45,7 +46,7 @@ export const testLogRows = (logRows: UpdateLog[], expectedLogRows: Partial<LogRo
|
||||
row.old_data === expectedRow.oldValue &&
|
||||
row.new_data === expectedRow.value
|
||||
)
|
||||
assert(!!receivedRow, 'Did not find relevant log row')
|
||||
assert(!!receivedRow, `Did not find this expected logrow: ${JSON.stringify(expectedRow)}`)
|
||||
const debugLog = `Row: \n${JSON.stringify(receivedRow, null, 2)}\nExpected:\n${JSON.stringify(expectedRow)}`
|
||||
assert(receivedRow.new_data === expectedRow.value, `Log rows new data differs. ${debugLog}`)
|
||||
assert(receivedRow.old_data === expectedRow.oldValue, `Log rows old data differs. ${debugLog}`)
|
||||
|
||||
Reference in New Issue
Block a user