Skip to content

Commit

Permalink
feat: Small fixes after review
Browse files Browse the repository at this point in the history
  • Loading branch information
doubleface authored and doubleface committed Feb 10, 2023
1 parent edf9f2a commit 4cf775c
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 108 deletions.
27 changes: 15 additions & 12 deletions packages/cozy-client/src/models/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function isPartnershipValid(partnership) {
* Normalize app manifest, retro-compatibility for old manifests
*
* @param {import('../types').Manifest} manifest - app manifest to normalize
* @returns {import('../types').Manifest}
* @returns {import('../types').SanitizedManifest}
*/
export function sanitize(manifest) {
const sanitized = { ...manifest }
Expand Down Expand Up @@ -124,8 +124,8 @@ export function sanitize(manifest) {
/**
* Ensures that fields has at least one field with the role 'identifier'
*
* @param {Object} [fields={}] Manifest fields
* @returns {Object} Sanitized manifest fields
* @param {import('../types').ManifestFields} fields - Manifest fields
* @returns {import('../types').ManifestFields} - Sanitized manifest fields
*/
export const sanitizeIdentifier = fields => {
const sanitized = _cloneDeep(fields)
Expand Down Expand Up @@ -155,11 +155,14 @@ export const sanitizeIdentifier = fields => {
/**
* Returns the key for the field having the role=identifier attribute
*
* @param {Object} fields Konnector fields
* @returns {string} The key for the identifier field, example 'login'
* @param {import('../types').ManifestFields} fields Konnector fields
* @returns {String|null} The key for the identifier field, example 'login'
*/
export const getIdentifier = (fields = {}) =>
findKey(sanitizeIdentifier(fields), field => field.role === ROLE_IDENTIFIER)
findKey(
sanitizeIdentifier(fields),
field => field.role === ROLE_IDENTIFIER
) || null
/**
* Ensures old fields are removed
*
Expand All @@ -175,8 +178,8 @@ const removeOldFields = fields => {
/**
* Ensures every field not explicitely tagged as not required is required
*
* @param {Object} [fields={}] Manifest fields
* @returns {Object} Sanitized manifest fields
* @param {import('../types').ManifestFields} [fields={}] Manifest fields
* @returns {import('../types').ManifestFields} Sanitized manifest fields
*/
const sanitizeRequired = fields => {
const sanitized = _cloneDeep(fields)
Expand All @@ -197,8 +200,8 @@ const sanitizeRequired = fields => {
* * any field flagged as encrypted keeps its flag
* * any legacy encrypted field is tagged as encrypted
*
* @param {Object} [fields={}] Manifest fields
* @returns {Object} Sanitized Manifest fields
* @param {import('../types').ManifestFields} [fields={}] Manifest fields
* @returns {import('../types').ManifestFields} Sanitized Manifest fields
*/
const sanitizeEncrypted = fields => {
const sanitized = _cloneDeep(fields)
Expand All @@ -214,8 +217,8 @@ const sanitizeEncrypted = fields => {
/**
* Sanitizes manifest fields with multiple rules
*
* @param {Object} [fields={}] Manifest fields
* @returns {Object} Sanitized manifest fields
* @param {import('../types').ManifestFields} [fields={}] Manifest fields
* @returns {import('../types').ManifestFields} Sanitized manifest fields
*/
const sanitizeFields = _flow([
removeOldFields,
Expand Down
189 changes: 93 additions & 96 deletions packages/cozy-client/src/models/manifest.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,93 +132,7 @@ describe('sanitizeManifest', () => {
})
})

describe('terms', () => {
it('should remove incomplete terms', () => {
const incompleteTerms = {
id: 'mock-terms'
}
expect(
sanitizeManifest({ ...baseMan, terms: incompleteTerms })
).not.toHaveProperty('terms')
expect(sanitizeManifest({ ...baseMan, terms: {} })).not.toHaveProperty(
'terms'
)
})

it('should keep complete terms', () => {
const completeTerms = {
id: 'mock-terms',
url: 'mock://terms',
version: 'mock001'
}
const man = { ...baseMan, terms: completeTerms }

expect(sanitizeManifest(man)).toEqual(expect.objectContaining(man))
})
})

describe('partnership', () => {
it('should remove incomplete', () => {
const incompletePartnership = {
icon: 'icon.svg' // icon is optional
}

expect(
sanitizeManifest({
...baseMan,
partnership: {}
})
).not.toHaveProperty('partnership')

expect(
sanitizeManifest({
...baseMan,
partnership: incompletePartnership
})
).not.toHaveProperty('partnership')
})

it('should keep complete', () => {
const completePartnership = {
description: 'A partnership text here' // description is mandatory
}

const man = { ...baseMan, partnership: completePartnership }
expect(sanitizeManifest(man)).toEqual(expect.objectContaining(man))
})
})
})

describe('getIdentifier', () => {
it('should return field having role=identifier', () => {
const fields = {
username: {
type: 'text'
},
id: {
type: 'text',
role: 'identifier'
}
}
expect(getIdentifier(fields)).toBe('id')
})

it('should return the first field', () => {
const fields = {
username: {
type: 'text'
},
id: {
type: 'text'
}
}

expect(getIdentifier(fields)).toBe('username')
})
})

describe('sanitizeFields', () => {
it('should remove old property advancedFields', () => {
it('should remove old property advancedFields in fields', () => {
const oldManifest = {
fields: {
login: {
Expand All @@ -239,8 +153,7 @@ describe('sanitizeFields', () => {
const result = sanitizeManifest(oldManifest)
expect(result.fields.advancedFields).toBeUndefined()
})
})
describe('sanitizeIdentifier', () => {

it('should not add any identifier', () => {
const current = {
fields: {
Expand Down Expand Up @@ -361,10 +274,8 @@ describe('sanitizeIdentifier', () => {
const result = sanitizeManifest(current)
expect(result.fields.login.required).toBe(true)
})
})

describe('sanitizeRequired', () => {
it('should set required=true as default value', () => {
it('should set required=true as default value in fields', () => {
const current = {
fields: {
login: { type: 'text' },
Expand All @@ -380,7 +291,7 @@ describe('sanitizeRequired', () => {
expect(result.fields.country.required).toBe(true)
})

it('should handle legacy property isRequired', () => {
it('should handle legacy property isRequired in fields', () => {
const current = {
fields: {
login: { type: 'text' },
Expand All @@ -395,10 +306,8 @@ describe('sanitizeRequired', () => {
expect(result.fields.gender.required).toBe(false)
expect(result.fields.country.required).toBe(true)
})
})

describe('sanitizeEncrypted', () => {
it('should et encrypted for type=password', () => {
it('should set encrypted for type=password fields', () => {
const current = {
fields: {
username: { type: 'text' },
Expand Down Expand Up @@ -446,4 +355,92 @@ describe('sanitizeEncrypted', () => {
expect(result.fields.passphrase.encrypted).toBe(true)
})
}

describe('terms', () => {
it('should remove incomplete terms', () => {
const incompleteTerms = {
id: 'mock-terms'
}
expect(
sanitizeManifest({ ...baseMan, terms: incompleteTerms })
).not.toHaveProperty('terms')
expect(sanitizeManifest({ ...baseMan, terms: {} })).not.toHaveProperty(
'terms'
)
})

it('should keep complete terms', () => {
const completeTerms = {
id: 'mock-terms',
url: 'mock://terms',
version: 'mock001'
}
const man = { ...baseMan, terms: completeTerms }

expect(sanitizeManifest(man)).toEqual(expect.objectContaining(man))
})
})

describe('partnership', () => {
it('should remove incomplete', () => {
const incompletePartnership = {
icon: 'icon.svg' // icon is optional
}

expect(
sanitizeManifest({
...baseMan,
partnership: {}
})
).not.toHaveProperty('partnership')

expect(
sanitizeManifest({
...baseMan,
partnership: incompletePartnership
})
).not.toHaveProperty('partnership')
})

it('should keep complete', () => {
const completePartnership = {
description: 'A partnership text here' // description is mandatory
}

const man = { ...baseMan, partnership: completePartnership }
expect(sanitizeManifest(man)).toEqual(expect.objectContaining(man))
})
})
})

describe('getIdentifier', () => {
it('should return field having role=identifier', () => {
const fields = {
username: {
type: 'text'
},
id: {
type: 'text',
role: 'identifier'
}
}
expect(getIdentifier(fields)).toBe('id')
})

it('should return the first field', () => {
const fields = {
username: {
type: 'text'
},
id: {
type: 'text'
}
}

expect(getIdentifier(fields)).toBe('username')
})

it('should return null if there is no match', () => {
expect(getIdentifier({})).toBe(null)
})
})
16 changes: 16 additions & 0 deletions packages/cozy-client/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ import { QueryDefinition } from './queries/dsl'
* @typedef {object} Token
* @typedef {object} ClientResponse
* @typedef {object} Manifest
* @typedef {object} SanitizedManifest
*/

/**
* @typedef {Object} ManifestField
* @property {String} [type] - field type : can be "text" or "hidden" or "date" or "dropdown" or "password"
* @property {String} [role] - field role : with "identifier" value
* @property {Boolean} [required] - is the field required or not
* @property {Boolean} [isRequired] - is the field required or not (legacy)
* @property {Boolean} [encrypted] - encrypted value of the field (legacy)
*/

/**
* @typedef {{
* [key: string]: ManifestField;
* }} ManifestFields
*/

/**
Expand Down

0 comments on commit 4cf775c

Please sign in to comment.