Skip to content

Commit

Permalink
Merge pull request #1458 from contentful/FUS-290
Browse files Browse the repository at this point in the history
feat: allow NER resource types in allowedResources
  • Loading branch information
BasKiers authored Jan 10, 2025
2 parents 9730637 + 3030e4b commit 0c2e44e
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 17 deletions.
18 changes: 13 additions & 5 deletions src/lib/offline-api/validator/schema/allowed-resources-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@ export const allowedResourcesSchema = Joi.array()
.max(MAX_ALLOWED_RESOURCES)
.unique('source')
.items(
Joi.object({
type: Joi.string().valid('Contentful:Entry'),
source: Joi.string(),
contentTypes: Joi.array().min(1).items(Joi.string())
})
Joi.alternatives().conditional(
Joi.object({ type: Joi.string().regex(/^Contentful:/) }).unknown(),
{
then: Joi.object({
type: Joi.string().valid('Contentful:Entry'),
source: Joi.string(),
contentTypes: Joi.array().min(1).items(Joi.string())
}),
otherwise: Joi.object({
type: Joi.string().regex(/^[A-Z][a-z]*:[A-Z][a-z]*$/)
})
}
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ describe('payload validation (dependencies)', function () {
})

describe('when setting a field to ResourceLink but specifying wrong resource properties', function () {
it('returns errors', async function () {
it('returns errors when an invalid ResourceType is provided for the Contentful: ResourceProvider', async function () {
const existingCts = []
const errors = await validateBatches(function (migration) {
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')
Expand All @@ -194,35 +194,133 @@ describe('payload validation (dependencies)', function () {
.name('Main Course')
.type('ResourceLink')
.allowedResources([
{
type: 'Contentful:Entry',
source: 'crn:contentful:::content:spaces/cooking-space-1',
contentTypes: []
},
{
type: 'Contentful:Asset',
source: 'crn:contentful:::content:spaces/cooking-space-2',
contentTypes: ['cookingMethod']
}
])
}, existingCts)

expect(errors).to.eql([
[
{
type: 'InvalidPayload',
message:
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "type" must be [Contentful:Entry].'
}
]
])
})

it('returns errors when the allowedResources of the Contentful: Provider contains additional fields', async function () {
const existingCts = []
const errors = await validateBatches(function (migration) {
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')

lunch
.createField('mainCourse')
.name('Main Course')
.type('ResourceLink')
.allowedResources([
{
type: 'Contentful:Entry',
source: 'crn:contentful:::content:spaces/cooking-space-1',
contentTypes: ['cookingMethod'],
unexpectedProperty: 'someValue'
}
])
}, existingCts)

expect(errors).to.eql([
[
{
message:
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "unexpectedProperty" is not allowed.',
type: 'InvalidPayload'
}
]
])
})

it('returns errors when the contentTypes array is empty', async function () {
const existingCts = []
const errors = await validateBatches(function (migration) {
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')

lunch
.createField('mainCourse')
.name('Main Course')
.type('ResourceLink')
.allowedResources([
{
type: 'Contentful:Entry',
source: 'crn:contentful:::content:spaces/cooking-space-1',
contentTypes: []
}
])
}, existingCts)

expect(errors).to.eql([
[
{
type: 'InvalidPayload',
message:
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "contentTypes" must contain at least 1 items.'
},
}
]
])
})

it('returns an error when the type value is referencing a invalid type', async function () {
const existingCts = []
const errors = await validateBatches(function (migration) {
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')

lunch
.createField('mainCourse')
.name('Main Course')
.type('ResourceLink')
.allowedResources([
{
type: 'Foo'
}
])
}, existingCts)

expect(errors).to.eql([
[
{
type: 'InvalidPayload',
message:
'Allowed resource at index 1 on the field "mainCourse" has an invalid property: "type" must be [Contentful:Entry].'
},
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "type" with value "Foo" fails to match the required pattern: /^[A-Z][a-z]*:[A-Z][a-z]*$/.',
type: 'InvalidPayload'
}
]
])
})

it('returns an error when the type value is referencing custom ResourceProvider:ResourceType pair with additional properties', async function () {
const existingCts = []
const errors = await validateBatches(function (migration) {
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')

lunch
.createField('mainCourse')
.name('Main Course')
.type('ResourceLink')
.allowedResources([
{
type: 'Foo:Bar',
source: 'crn:contentful:::content:spaces/cooking-space-2'
}
])
}, existingCts)

expect(errors).to.eql([
[
{
message:
'Allowed resource at index 1 on the field "mainCourse" has an invalid property: "unexpectedProperty" is not allowed.',
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "source" is not allowed.',
type: 'InvalidPayload'
}
]
Expand All @@ -245,6 +343,25 @@ describe('payload validation (dependencies)', function () {

expect(errors).to.eql([[]])
})

it('should not return an error when the type value is referencing a custom ResourceProvider:ResourceType pair', async function () {
const existingCts = []
const errors = await validateBatches(function (migration) {
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')

lunch
.createField('mainCourse')
.name('Main Course')
.type('ResourceLink')
.allowedResources([
{
type: 'Foo:Bar'
}
])
}, existingCts)

expect(errors).to.eql([[]])
})
})

describe('when setting a field to ResourceLink with duplicate sources in allowedResources', function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ describe('payload validation (dependencies)', function () {
])
})

it('should return an error when the type value is not one of the supported values', async function () {
it('should return an error when the type value is not one of the supported values for the Contentful: Provider', async function () {
const existingCts = []
const errors = await validateBatches(function (migration) {
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')
Expand Down

0 comments on commit 0c2e44e

Please sign in to comment.