diff --git a/proto/observation/v5.proto b/proto/observation/v5.proto index f224fdda..dd807e29 100644 --- a/proto/observation/v5.proto +++ b/proto/observation/v5.proto @@ -14,8 +14,8 @@ message Observation_5 { Common_1 common = 1; - optional float lat = 5; - optional float lon = 6; + optional double lat = 5; + optional double lon = 6; message Ref { bytes id = 1; @@ -47,12 +47,12 @@ message Observation_5 { bool mocked = 2; message Coords { - float latitude = 1; - float longitude = 2; - float altitude = 3; - float heading = 4; - float speed = 5; - float acurracy = 6; + double latitude = 1; + double longitude = 2; + double altitude = 3; + double heading = 4; + double speed = 5; + double accuracy = 6; } optional Coords coords = 3; } diff --git a/schema/preset/v2.json b/schema/preset/v2.json index 2852c2d3..d44676bc 100644 --- a/schema/preset/v2.json +++ b/schema/preset/v2.json @@ -83,7 +83,7 @@ "type": "string" } }, - "icon": { + "iconId": { "description": "hex-encoded string. ID of preset icon which represents this preset", "type": "string" }, diff --git a/src/lib/decode-conversions.ts b/src/lib/decode-conversions.ts index 99144658..b85f3330 100644 --- a/src/lib/decode-conversions.ts +++ b/src/lib/decode-conversions.ts @@ -32,12 +32,12 @@ export const convertProject: ConvertFunction<'project'> = ( ...jsonSchemaCommon, ...rest, defaultPresets: { - point: message.defaultPresets?.point.map(p => p.toString('hex')), - area: message.defaultPresets?.area.map(a => a.toString('hex')), - vertex: message.defaultPresets?.vertex.map(v => v.toString('hex')), - line: message.defaultPresets?.line.map(l => l.toString('hex')), - relation: message.defaultPresets?.relation.map(r => r.toString('hex')), - } + point: message.defaultPresets?.point.map((p) => p.toString('hex')), + area: message.defaultPresets?.area.map((a) => a.toString('hex')), + vertex: message.defaultPresets?.vertex.map((v) => v.toString('hex')), + line: message.defaultPresets?.line.map((l) => l.toString('hex')), + relation: message.defaultPresets?.relation.map((r) => r.toString('hex')), + }, } } @@ -113,6 +113,7 @@ export const convertPreset: ConvertFunction<'preset'> = ( ...jsonSchemaCommon, ...rest, geometry, + iconId: rest.iconId ? rest.iconId.toString('hex') : undefined, tags: convertTags(rest.tags), addTags: convertTags(rest.addTags), removeTags: convertTags(rest.removeTags), @@ -120,19 +121,16 @@ export const convertPreset: ConvertFunction<'preset'> = ( } } -export const convertRole: ConvertFunction<'role'> = ( -message, -versionObj -) => { - const { common, schemaVersion, ...rest } = message - const jsonSchemaCommon = convertCommon(common, versionObj) - return { - ...jsonSchemaCommon, - ...rest, +export const convertRole: ConvertFunction<'role'> = (message, versionObj) => { + const { common, schemaVersion, ...rest } = message + const jsonSchemaCommon = convertCommon(common, versionObj) + return { + ...jsonSchemaCommon, + ...rest, role: rest.role, projectId: message.projectId.toString('hex'), - authorId: message.authorId.toString('hex') - } + authorId: message.authorId.toString('hex'), + } } export const convertDevice: ConvertFunction<'device'> = ( @@ -145,7 +143,7 @@ export const convertDevice: ConvertFunction<'device'> = ( ...jsonSchemaCommon, ...rest, authorId: message.authorId.toString('hex'), - projectId: message.projectId.toString('hex') + projectId: message.projectId.toString('hex'), } } @@ -160,9 +158,8 @@ export const convertCoreOwnership: ConvertFunction<'coreOwnership'> = ( ...rest, coreId: message.coreId.toString('hex'), projectId: message.projectId.toString('hex'), - authorId: message.authorId.toString('hex') + authorId: message.authorId.toString('hex'), } - } function convertTags(tags: { [key: string]: TagValue_1 } | undefined): { diff --git a/src/lib/encode-converstions.ts b/src/lib/encode-converstions.ts index f95e2e28..c8baae55 100644 --- a/src/lib/encode-converstions.ts +++ b/src/lib/encode-converstions.ts @@ -26,12 +26,22 @@ export const convertProject: ConvertFunction<'project'> = (mapeoDoc) => { common: convertCommon(mapeoDoc), ...mapeoDoc, defaultPresets: { - point: (mapeoDoc.defaultPresets.point || []).map(p => Buffer.from(p,'hex')), - area: (mapeoDoc.defaultPresets.area || []).map(a => Buffer.from(a,'hex')), - vertex: (mapeoDoc.defaultPresets.area || []).map(v => Buffer.from(v,'hex')), - line: (mapeoDoc.defaultPresets.area || []).map(l => Buffer.from(l, 'hex')), - relation: (mapeoDoc.defaultPresets.area || []).map(r => Buffer.from(r, 'hex')) - } + point: (mapeoDoc.defaultPresets.point || []).map((p) => + Buffer.from(p, 'hex') + ), + area: (mapeoDoc.defaultPresets.area || []).map((a) => + Buffer.from(a, 'hex') + ), + vertex: (mapeoDoc.defaultPresets.vertex || []).map((v) => + Buffer.from(v, 'hex') + ), + line: (mapeoDoc.defaultPresets.line || []).map((l) => + Buffer.from(l, 'hex') + ), + relation: (mapeoDoc.defaultPresets.relation || []).map((r) => + Buffer.from(r, 'hex') + ), + }, } } @@ -64,7 +74,7 @@ export const convertPreset: ConvertFunction<'preset'> = (mapeoDoc) => { addTags: convertTags(mapeoDoc.addTags), removeTags: convertTags(mapeoDoc.removeTags), fieldIds: mapeoDoc.fieldIds.map((field) => Buffer.from(field, 'hex')), - iconId: mapeoDoc.icon ? Buffer.from(mapeoDoc.icon, 'hex') : undefined, + iconId: mapeoDoc.iconId ? Buffer.from(mapeoDoc.iconId, 'hex') : undefined, } } @@ -94,26 +104,21 @@ export const convertObservation: ConvertFunction<'observation'> = ( } } -export const convertRole: ConvertFunction<'role'> = ( - mapeoDoc -) => { +export const convertRole: ConvertFunction<'role'> = (mapeoDoc) => { return { common: convertCommon(mapeoDoc), ...mapeoDoc, - projectId: Buffer.from(mapeoDoc.projectId,'hex'), - authorId: Buffer.from(mapeoDoc.authorId,'hex') - + projectId: Buffer.from(mapeoDoc.projectId, 'hex'), + authorId: Buffer.from(mapeoDoc.authorId, 'hex'), } } -export const convertDevice: ConvertFunction<'device'> = ( - mapeoDoc -) => { +export const convertDevice: ConvertFunction<'device'> = (mapeoDoc) => { return { common: convertCommon(mapeoDoc), ...mapeoDoc, authorId: Buffer.from(mapeoDoc.authorId, 'hex'), - projectId: Buffer.from(mapeoDoc.projectId, 'hex') + projectId: Buffer.from(mapeoDoc.projectId, 'hex'), } } @@ -125,7 +130,7 @@ export const convertCoreOwnership: ConvertFunction<'coreOwnership'> = ( ...mapeoDoc, coreId: Buffer.from(mapeoDoc.coreId, 'hex'), projectId: Buffer.from(mapeoDoc.projectId, 'hex'), - authorId: Buffer.from(mapeoDoc.authorId,'hex') + authorId: Buffer.from(mapeoDoc.authorId, 'hex'), } } @@ -145,14 +150,10 @@ function convertTags(tags: { }): { [key: string]: TagValue_1 } { - return Object.keys(tags).reduce( - (acc: { [key: string]: TagValue_1 }, k: string) => { - return { - [k]: convertTagValue(tags[k]), - } - }, - {} - ) + return Object.keys(tags).reduce<{ [key: string]: TagValue_1 }>((acc, k) => { + acc[k] = convertTagValue(tags[k]) + return acc + }, {}) } function convertTagValue(tagValue: JsonTagValue): TagValue_1 { diff --git a/test/docs.js b/test/docs.js deleted file mode 100644 index e6553431..00000000 --- a/test/docs.js +++ /dev/null @@ -1,104 +0,0 @@ -import { randomBytes } from 'node:crypto' - -export const docs = { - onlyId: { id: randomBytes(32).toString('hex') }, - badDocType: { - id: randomBytes(32).toString('hex'), - schemaType: 'doesnotexist', - links: [], - createdAt: new Date().toJSON(), - refs: [], - attachments: [], - metadata: { - manual_location: true, - }, - }, - badSchemaVersion: { - id: randomBytes(32).toString('hex'), - schemaType: 'observation', - schemaVersion: 2, - links: [], - createdAt: new Date().toJSON(), - refs: [], - attachments: [], - metadata: { - manual_location: true, - }, - }, - good: { - observation_5: { - id: randomBytes(32).toString('hex'), - schemaType: 'observation', - createdAt: new Date().toJSON(), - updatedAt: new Date().toJSON(), - links: [], - tags: { fields: { myTag: 10 } }, - }, - preset: { - id: randomBytes(32).toString('hex'), - createdAt: new Date().toJSON(), - updatedAt: new Date().toJSON(), - schemaType: 'preset', - links: [], - tags: { nature: 'tree' }, - geometry: ['point'], - name: 'john', - }, - field: { - id: randomBytes(32).toString('hex'), - createdAt: new Date().toJSON(), - updatedAt: new Date().toJSON(), - schemaType: 'field', - tagKey: 'hi', - type: 'text', - links: [], - }, - coreOwnership: { - schemaType: 'coreOwnership', - id: randomBytes(32).toString('hex'), - coreId: randomBytes(32).toString('hex'), - projectId: randomBytes(32).toString('hex'), - storeType: 'blob', - authorIndex: 10, - deviceIndex: 10, - action: 'core:owner', - createdAt: new Date().toJSON(), - updatedAt: new Date().toJSON(), - links: [], - }, - device: { - schemaType: 'device', - id: randomBytes(32).toString('hex'), - action: 'device:add', - authorId: randomBytes(32).toString('hex'), - projectId: randomBytes(32).toString('hex'), - signature: 'hi', - authorIndex: 10, - deviceIndex: 10, - createdAt: new Date().toJSON(), - updatedAt: new Date().toJSON(), - links: [], - }, - role: { - id: randomBytes(32).toString('hex'), - schemaType: 'role', - role: 'project-creator', - projectId: randomBytes(32).toString('hex'), - action: 'role:set', - signature: 'hi', - authorIndex: 10, - deviceIndex: 10, - createdAt: new Date().toJSON(), - updatedAt: new Date().toJSON(), - links: [], - }, - project: { - id: randomBytes(32).toString('hex'), - schemaType: 'project', - createdAt: new Date().toJSON(), - updatedAt: new Date().toJSON(), - name: 'My Project', - links: [], - }, - }, -} diff --git a/test/fixtures/bad-docs.js b/test/fixtures/bad-docs.js new file mode 100644 index 00000000..083934c5 --- /dev/null +++ b/test/fixtures/bad-docs.js @@ -0,0 +1,26 @@ +// @ts-check +import { randomBytes } from 'node:crypto' +import { cachedValues } from './cached.js' + +export const badDocs = [ + { + text: 'test encoding of record with missing fields', + doc: { docId: randomBytes(32).toString('hex') }, + }, + { + text: 'test encoding of wrong schema name', + /** @type Omit & { schemaName: string }} */ + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'observOtion', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + refs: [], + attachments: [], + tags: {}, + metadata: {}, + }, + }, +] diff --git a/test/fixtures/cached.js b/test/fixtures/cached.js new file mode 100644 index 00000000..58c5b950 --- /dev/null +++ b/test/fixtures/cached.js @@ -0,0 +1,28 @@ +import { randomBytes } from 'node:crypto' + +// For stuff like dates or generated random Ids, so I can compare with an expected doc +const date = new Date().toJSON() +export const cachedValues = { + docId: randomBytes(32).toString('hex'), + versionId: `${randomBytes(32).toString('hex')}/0`, + projectId: randomBytes(32).toString('hex'), + authorId: randomBytes(32).toString('hex'), + coreId: randomBytes(32).toString('hex'), + createdAt: date, + updatedAt: date, + attachments: { driveId: randomBytes(32).toString('hex') }, + metadata: { + position: { + timestamp: date, + }, + }, + defaultPresets: { + point: [randomBytes(32).toString('hex')], + area: [randomBytes(32).toString('hex')], + vertex: [randomBytes(32).toString('hex')], + line: [randomBytes(32).toString('hex')], + relation: [randomBytes(32).toString('hex')], + }, + fieldIds: [randomBytes(32).toString('hex')], + iconId: randomBytes(32).toString('hex'), +} diff --git a/test/fixtures/good-docs-completed.js b/test/fixtures/good-docs-completed.js new file mode 100644 index 00000000..327983bc --- /dev/null +++ b/test/fixtures/good-docs-completed.js @@ -0,0 +1,195 @@ +// @ts-check + +import { cachedValues } from './cached.js' + +/** + * @type {Array<{ + * expected: Partial, + * doc: import('../../dist/types').MapeoDoc + * }>} + */ +export const goodDocsCompleted = [ + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'observation', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + lat: 24.0424, + lon: 21.0214, + refs: [], + attachments: [ + { + name: 'myFile', + type: 'photo', + driveId: cachedValues.attachments.driveId, + }, + ], + tags: { + someKeyForSingleVal: 'someVal', + someKeyForArrVal: ['arr', 'of', 'strings'], + }, + metadata: { + manualLocation: true, + position: { + timestamp: cachedValues.metadata.position.timestamp, + mocked: false, + coords: { + latitude: 0.5, + longitude: -0.2, + altitude: 0.8, + heading: 1.2, + speed: 0.7, + accuracy: 1.3, + }, + }, + lastSavedPosition: { + timestamp: cachedValues.metadata.position.timestamp, + mocked: true, + coords: { + latitude: 1.5, + longitude: -2.3, + altitude: 1000.1, + heading: 0.2, + speed: 0.1, + accuracy: 8.3, + }, + }, + positionProvider: { + gpsAvailable: true, + passiveAvailable: false, + locationServicesEnabled: true, + networkAvailable: false, + }, + }, + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'project', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + defaultPresets: { + point: cachedValues.defaultPresets.point, + area: cachedValues.defaultPresets.point, + vertex: cachedValues.defaultPresets.point, + line: cachedValues.defaultPresets.point, + relation: cachedValues.defaultPresets.point, + }, + name: 'myProject', + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'field', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + tagKey: 'otherTagKey', + type: 'number', + label: 'differentLabel', + appearance: 'singleline', + snakeCase: true, + universal: true, + options: [ + { + label: 'someOtherLabel', + value: 'somePrimitiveTagValue', + }, + ], + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'preset', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + name: 'myPreset', + geometry: ['point', 'vertex', 'line'], + tags: { + someKeyForArrVal: ['arr', 'of', 'strings'], + }, + addTags: { + heyAddThisTag: 'pleease', + orMaybeThis: ['right?', '', 'that was empty'], + }, + removeTags: { + deleteInmeditaly: ['this list', 'of things'], + }, + fieldIds: cachedValues.fieldIds, + iconId: cachedValues.iconId, + terms: ['imastring'], + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'role', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + role: 'author', + projectId: cachedValues.projectId, + action: 'role_set', + signature: 'signature', + authorIndex: 8, + deviceIndex: 7, + authorId: cachedValues.authorId, + capabilityType: 'capability', + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'device', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + action: 'ban', + authorId: cachedValues.authorId, + projectId: cachedValues.projectId, + signature: 'mySignature', + authorIndex: 1, + deviceIndex: 10, + capabilityType: 'someCapability', + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'coreOwnership', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + action: 'remove', + coreId: cachedValues.coreId, + projectId: cachedValues.projectId, + storeType: 'blob', + signature: 'mySig', + authorIndex: 100, + deviceIndex: 2, + authorId: cachedValues.authorId, + capabilityType: 'someCapability', + }, + expected: {}, + }, +] diff --git a/test/fixtures/good-docs-minimal.js b/test/fixtures/good-docs-minimal.js new file mode 100644 index 00000000..865e1f46 --- /dev/null +++ b/test/fixtures/good-docs-minimal.js @@ -0,0 +1,144 @@ +// @ts-check +import { cachedValues } from './cached.js' + +/** + * The `expected` is a partial doc of the extra fields that we expect to be set + * by the encode/decode round-trip + * + * @type {Array<{ + * expected: Partial, + * doc: import('../../dist/types').MapeoDoc + * }>} + */ +export const goodDocsMinimal = [ + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'observation', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + refs: [], + attachments: [], + tags: {}, + metadata: {}, + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'project', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + defaultPresets: {}, + name: 'myProject', + }, + expected: { + defaultPresets: { + point: [], + area: [], + vertex: [], + line: [], + relation: [], + }, + }, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'field', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + tagKey: 'myTagKey', + label: 'my label', + type: 'text', + }, + expected: { + appearance: 'multiline', + snakeCase: false, + options: [], + universal: false, + }, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'preset', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + name: 'myPreset', + geometry: ['point'], + tags: {}, + addTags: {}, + removeTags: {}, + fieldIds: [], + terms: [], + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'role', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + role: 'author', + projectId: cachedValues.projectId, + signature: 'signature', + authorId: cachedValues.authorId, + capabilityType: 'capability', + authorIndex: 0, + deviceIndex: 0, + action: 'UNRECOGNIZED', + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'device', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + action: 'ban', + authorId: cachedValues.authorId, + projectId: cachedValues.projectId, + signature: 'mySignature', + capabilityType: 'someCapability', + authorIndex: 0, + deviceIndex: 0, + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + schemaName: 'coreOwnership', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + action: 'remove', + coreId: cachedValues.coreId, + projectId: cachedValues.projectId, + storeType: 'blob', + signature: 'mySig', + authorId: cachedValues.authorId, + capabilityType: 'someCapability', + authorIndex: 0, + deviceIndex: 0, + }, + expected: {}, + }, +] diff --git a/test/fixtures/index.js b/test/fixtures/index.js new file mode 100644 index 00000000..1b5bd89b --- /dev/null +++ b/test/fixtures/index.js @@ -0,0 +1,3 @@ +export * from './bad-docs.js' +export * from './good-docs-completed.js' +export * from './good-docs-minimal.js' diff --git a/test/index.js b/test/index.js index 66ed619e..f8157595 100644 --- a/test/index.js +++ b/test/index.js @@ -1,88 +1,70 @@ +// @ts-check import test from 'tape' -import { encode, decode, validate } from '../index.js' -import { randomBytes } from 'node:crypto' -import { docs } from './docs.js' +import { encode, decode } from '../dist/index.js' +import { parseVersionId } from '../dist/index.js' +import { + goodDocsMinimal, + goodDocsCompleted, + badDocs, +} from './fixtures/index.js' -test('test encoding of record with missing fields', async (t) => { - t.plan(1) - t.throws(() => { - encode(docs.onlyId) - }) -}) - -test('test encoding of wrong record type', async (t) => { - t.plan(1) - t.throws(() => { - encode(docs.badDocType) - }) -}) - -test('test encoding of record with wrong schema version', async (t) => { - t.plan(1) - t.throws(() => { - encode(docs.badSchemaVersion) - }) -}) - -test('test encoding of rightfully formated record', async (t) => { - const goodDocs = Object.keys(docs.good) - t.plan(goodDocs.length) - goodDocs.forEach((k) => { - const doc = docs.good[k] - t.doesNotThrow(() => { +test('Bad docs throw when encoding', (t) => { + for (const { text, doc } of badDocs) { + t.throws(() => { + // @ts-expect-error encode(doc) - }, `testing ${k}`) - }) + }, text) + } + t.end() }) -test('test validation of record', async (t) => { - const goodDocs = Object.keys(docs.good) - t.plan(goodDocs.length) - goodDocs.forEach((k) => { - const doc = docs.good[k] - const record = decode(encode(doc), { - coreKey: randomBytes(32), - index: 0, - }) - t.doesNotThrow(() => { - // field has a type which is different from the rest :| - if (k !== 'field') validate(record) - }, `testing validation of ${k}`) - }) +test(`testing encoding of doc with minimal required values, + then decoding and comparing the two objects`, async (t) => { + for (const { doc, expected } of goodDocsMinimal) { + const buf = encode(doc) + const decodedDoc = stripUndef(decode(buf, parseVersionId(doc.versionId))) + t.deepEqual( + decodedDoc, + { ...doc, ...expected }, + `tested deep equal of ${doc.schemaName} with only required values` + ) + } }) -test('test encoding, decoding of record and comparing the two versions', async (t) => { - const goodDocs = Object.keys(docs.good) - goodDocs.forEach((k) => { - const doc = docs.good[k] - const record = decode(encode(doc), { - coreKey: randomBytes(32), - index: 0, - }) - const fields = Object.keys(doc) - // t.plan(goodDocs.length * fields.length * 2) - fields.forEach((f) => { - console.log(typeof record[f], typeof doc[f]) - const msg = `checking ${f} for ${k}` - record[f] && doc[f] ? t.pass(msg) : t.fail(msg) +test(`testing encoding of doc with additional optional values, + then decoding and comparing the two objects`, async (t) => { + for (const { doc, expected } of goodDocsCompleted) { + const buf = encode(doc) + const decodedDoc = stripUndef(decode(buf, parseVersionId(doc.versionId))) + t.deepEqual( + decodedDoc, + { ...doc, ...expected }, + `tested deep equal of ${doc.schemaName} with additional values` + ) + } +}) - // if field is not an object, check equality - // since objects as fields usually mean the possibility of additionalFields in jsonSchemas - if (typeof record[f] !== 'object') { - t.equal(record[f], doc[f], `comparing value of ${f} for ${k}`) - } +test(`testing encoding of doc with additional extra values, +then decoding and comparing the two objects - extra values shouldn't be present`, async (t) => { + for (const { doc, expected } of goodDocsCompleted) { + const buf = encode({ + ...doc, + // @ts-expect-error + extraFieldNotInSchema: 'whatever', }) - }) + const decodedDoc = stripUndef(decode(buf, parseVersionId(doc.versionId))) + t.deepEqual( + decodedDoc, + { ...doc, ...expected }, + `tested deep equal of ${doc.schemaName} with extra - non valid - values` + ) + } }) -test('test decoding of record without passing core key and index', async (t) => { - const goodDocs = Object.keys(docs.good) - t.plan(goodDocs.length) - goodDocs.forEach((key) => { - const doc = docs.good[key] - const record = encode(doc) - t.throws(() => { - decode(record) - }, `testing ${key}`) - }) -}) +/** + * @param {object} obj + * @return {object} + * */ +function stripUndef(obj) { + return JSON.parse(JSON.stringify(obj)) +}