synctos
Version:
The Syncmaker. A tool to build comprehensive sync functions for Couchbase Sync Gateway.
562 lines (514 loc) • 18.4 kB
JavaScript
const testFixtureMaker = require('../src/testing/test-fixture-maker');
const errorFormatter = require('../src/testing/validation-error-formatter');
describe('File attachment constraints:', () => {
const testFixture =
testFixtureMaker.initFromSyncFunction('build/sync-functions/test-attachment-constraints-sync-function.js');
afterEach(() => {
testFixture.resetTestEnvironment();
});
describe('with static validation', () => {
describe('a document type that does not require an attachment reference for each file attachment', () => {
it('should allow creation of a document whose attachments do not violate the constraints', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.pdf': {
length: 20,
content_type: 'application/pdf'
},
'bar.html': {
length: 15,
content_type: 'text/html'
},
'other.foo': {
length: 5,
content_type: 'text/bar'
}
},
type: 'staticRegularAttachmentsDoc',
attachmentRefProp: 'other.foo' // The attachmentReference overrides supported extensions, content types and the regex pattern
};
testFixture.verifyDocumentCreated(doc);
});
it('should allow replacement when document attachments do not violate the constraints', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.xml': {
length: 40,
content_type: 'application/xml'
}
},
type: 'staticRegularAttachmentsDoc',
attachmentRefProp: 'foo.xml' // The attachmentReference's maximum size of 40 overrides the document's maximum individual size of 25
};
const oldDoc = {
_id: 'myDoc',
type: 'staticRegularAttachmentsDoc'
};
testFixture.verifyDocumentReplaced(doc, oldDoc);
});
describe('maximum attachment size constraints', () => {
it('should block creation of a document whose attachments exceed the limits', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.pdf': {
length: 5,
content_type: 'application/pdf'
},
'bar.html': {
length: 35,
content_type: 'text/html'
},
'baz.txt': {
length: 1,
content_type: 'text/plain'
}
},
type: 'staticRegularAttachmentsDoc',
attachmentRefProp: 'bar.html' // The attachmentReference's maximum size of 40 overrides the document's maximum individual size of 25
};
testFixture.verifyDocumentNotCreated(
doc,
'staticRegularAttachmentsDoc',
errorFormatter.maximumTotalAttachmentSizeViolation(40));
});
it('should block replacement when document attachments exceed the limits', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.xml': {
length: 41,
content_type: 'application/xml'
}
},
type: 'staticRegularAttachmentsDoc'
};
const oldDoc = {
_id: 'myDoc',
type: 'staticRegularAttachmentsDoc'
};
testFixture.verifyDocumentNotReplaced(
doc,
oldDoc,
'staticRegularAttachmentsDoc',
[
errorFormatter.maximumTotalAttachmentSizeViolation(40),
errorFormatter.maximumIndividualAttachmentSizeViolation('foo.xml', 25)
]);
});
});
describe('maximum attachment count constraint', () => {
it('should block creation of a document whose number of attachments exceed the limit', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.pdf': {
length: 10,
content_type: 'application/pdf',
},
'bar.html': {
length: 10,
content_type: 'text/html'
},
'baz.txt': {
length: 10,
content_type: 'text/plain'
},
'qux.jpg': {
length: 10,
content_type: 'image/jpeg'
}
},
type: 'staticRegularAttachmentsDoc'
};
testFixture.verifyDocumentNotCreated(
doc,
'staticRegularAttachmentsDoc',
errorFormatter.maximumAttachmentCountViolation(3));
});
it('should block replacement when document attachments exceed the limit', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.xml': {
length: 10,
content_type: 'application/xml',
},
'bar.html': {
length: 10,
content_type: 'text/html'
},
'baz.txt': {
length: 10,
content_type: 'text/plain'
},
'qux.jpg': {
length: 10,
content_type: 'image/jpeg'
}
},
type: 'staticRegularAttachmentsDoc'
};
const oldDoc = {
_id: 'myDoc',
type: 'staticRegularAttachmentsDoc'
};
testFixture.verifyDocumentNotReplaced(
doc,
oldDoc,
'staticRegularAttachmentsDoc',
errorFormatter.maximumAttachmentCountViolation(3));
});
});
describe('supported file extensions constraint', () => {
const expectedExtensions = [ 'html', 'jpg', 'pdf', 'txt', 'xml' ];
it('should block creation of a document whose attachments have unsupported extensions', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.invalid': {
length: 10,
content_type: 'text/plain'
},
'bar.html': {
length: 10,
content_type: 'text/html'
},
'baz.unknown': {
length: 20,
content_type: 'application/xml'
}
},
type: 'staticRegularAttachmentsDoc'
};
testFixture.verifyDocumentNotCreated(
doc,
'staticRegularAttachmentsDoc',
[
errorFormatter.supportedExtensionsRawAttachmentViolation('baz.unknown', expectedExtensions),
errorFormatter.supportedExtensionsRawAttachmentViolation('foo.invalid', expectedExtensions)
]);
});
it('should block replacement when document attachments have unsupported extensions', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.invalid': {
length: 5,
content_type: 'image/jpeg'
},
'bar.foo': {
length: 5,
content_type: 'text/plain'
}
},
type: 'staticRegularAttachmentsDoc',
attachmentRefProp: 'bar.foo' // The attachmentReference's supported extensions override the document's supported extensions
};
const oldDoc = {
_id: 'myDoc',
type: 'staticRegularAttachmentsDoc'
};
testFixture.verifyDocumentNotReplaced(
doc,
oldDoc,
'staticRegularAttachmentsDoc',
errorFormatter.supportedExtensionsRawAttachmentViolation('foo.invalid', expectedExtensions));
});
});
describe('supported content types constraint', () => {
const expectedContentTypes = [ 'text/html', 'image/jpeg', 'application/pdf', 'text/plain', 'application/xml' ];
it('should block creation of a document whose attachments have unsupported content types', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.txt': {
length: 10,
content_type: 'text/invalid'
},
'bar.html': {
length: 10,
content_type: 'text/html'
},
'baz.xml': {
length: 20,
content_type: 'application/unknown'
}
},
type: 'staticRegularAttachmentsDoc'
};
testFixture.verifyDocumentNotCreated(
doc,
'staticRegularAttachmentsDoc',
[
errorFormatter.supportedContentTypesRawAttachmentViolation('baz.xml', expectedContentTypes),
errorFormatter.supportedContentTypesRawAttachmentViolation('foo.txt', expectedContentTypes)
]);
});
it('should block replacement when document attachments have unsupported content types', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.jpg': {
length: 5,
content_type: 'completely-invalid'
},
'bar.txt': {
length: 5,
content_type: 'text/bar'
}
},
type: 'staticRegularAttachmentsDoc',
attachmentRefProp: 'bar.txt' // The attachmentReference's supported content types override the document's supported content types
};
const oldDoc = {
_id: 'myDoc',
type: 'staticRegularAttachmentsDoc'
};
testFixture.verifyDocumentNotReplaced(
doc,
oldDoc,
'staticRegularAttachmentsDoc',
errorFormatter.supportedContentTypesRawAttachmentViolation('foo.jpg', expectedContentTypes));
});
});
});
describe('a document type that DOES require an attachment reference for each file attachment', () => {
it('should allow creation of a document whose attachments do not violate the constraint', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.pdf': {
length: 20721,
content_type: 'application/pdf'
}
},
type: 'staticAttachmentRefsOnlyDoc',
attachmentRefProp: 'foo.pdf'
};
testFixture.verifyDocumentCreated(doc);
});
it('should block creation of a document whose attachments violate the constraint', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.pdf': {
length: 6253,
content_type: 'application/pdf'
},
'bar.txt': {
length: 5701,
content_type: 'text/plain'
}
},
type: 'staticAttachmentRefsOnlyDoc',
attachmentRefProp: 'foo.pdf'
};
testFixture.verifyDocumentNotCreated(
doc,
'staticAttachmentRefsOnlyDoc',
errorFormatter.requireAttachmentReferencesViolation('bar.txt'));
});
it('should allow replacement when document attachments do not violate the constraint', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'bar.xml': {
length: 992,
content_type: 'application/xml'
}
},
type: 'staticAttachmentRefsOnlyDoc',
attachmentRefProp: 'bar.xml'
};
const oldDoc = {
_id: 'myDoc',
type: 'staticAttachmentRefsOnlyDoc'
};
testFixture.verifyDocumentReplaced(doc, oldDoc);
});
it('should block replacement when document attachments violate the constraint', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'bar.xml': {
length: 404,
content_type: 'application/xml'
},
'baz.jpg': {
length: 57922,
content_type: 'image/jpeg'
}
},
type: 'staticAttachmentRefsOnlyDoc',
attachmentRefProp: 'bar.xml'
};
const oldDoc = {
_id: 'myDoc',
type: 'staticAttachmentRefsOnlyDoc'
};
testFixture.verifyDocumentNotReplaced(
doc,
oldDoc,
'staticAttachmentRefsOnlyDoc',
errorFormatter.requireAttachmentReferencesViolation('baz.jpg'));
});
});
describe('filename regex pattern validation', () => {
const expectedRegexPattern = /^(foo|bar)\.(xls|xlsx)$/;
it('should allow document creation when document attachment names satisfy the regex', () => {
const doc = {
_id: 'my-doc',
type: 'staticAttachmentFilenameRegexPatternDoc',
_attachments: {
'foo.xls': { },
'bar.xlsx': { }
}
};
testFixture.verifyDocumentCreated(doc);
});
it('should allow document replacement when document attachment names satisfy the regex', () => {
const doc = {
_id: 'my-doc',
type: 'staticAttachmentFilenameRegexPatternDoc',
_attachments: {
'foo.xlsx': { }
}
};
const oldDoc = {
_id: 'my-doc',
type: 'staticAttachmentFilenameRegexPatternDoc'
};
testFixture.verifyDocumentReplaced(doc, oldDoc);
});
it('should block document creation when document attachment names violate the regex', () => {
const doc = {
_id: 'my-doc',
type: 'staticAttachmentFilenameRegexPatternDoc',
_attachments: {
'foo.txt': { },
'invalid.xls': { }
}
};
testFixture.verifyDocumentNotCreated(
doc,
'staticAttachmentFilenameRegexPatternDoc',
[
errorFormatter.attachmentFilenameRegexPatternViolation('foo.txt', expectedRegexPattern),
errorFormatter.attachmentFilenameRegexPatternViolation('invalid.xls', expectedRegexPattern)
]);
});
it('should block document replacement when document attachment names violate the regex', () => {
const doc = {
_id: 'my-doc',
type: 'staticAttachmentFilenameRegexPatternDoc',
_attachments: {
'foobar': { }
}
};
const oldDoc = {
_id: 'my-doc',
type: 'staticAttachmentFilenameRegexPatternDoc'
};
testFixture.verifyDocumentNotReplaced(
doc,
oldDoc,
'staticAttachmentFilenameRegexPatternDoc',
[ errorFormatter.attachmentFilenameRegexPatternViolation('foobar', expectedRegexPattern) ]);
});
});
});
describe('with dynamic validation', () => {
it('should allow creation of a document whose attachments do not violate the constraints', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.pdf': {
length: 20,
content_type: 'application/pdf'
},
'bar.html': {
length: 15,
content_type: 'text/html'
},
'baz.foo': {
length: 5,
content_type: 'text/bar'
}
},
type: 'dynamicAttachmentsDoc',
attachmentsEnabled: true,
maximumIndividualSize: 20,
maximumTotalSize: 40,
maximumAttachmentCount: 3,
supportedExtensions: [ 'pdf', 'html', 'foo' ],
supportedContentTypes: [ 'application/pdf', 'text/html', 'text/bar' ],
requireAttachmentReferences: true,
attachmentReferences: [ 'foo.pdf', 'bar.html', 'baz.foo' ],
filenameRegexPattern: '^(foo|bar|baz)\\..*$'
};
testFixture.verifyDocumentCreated(doc);
});
it('should block creation of a document whose attachments violate the constraints', () => {
const supportedExtensions = [ 'pdf', 'foo' ];
const supportedContentTypes = [ 'application/pdf', 'text/html' ];
const filenameRegexString = '^(bar|baz)\\..*$';
const doc = {
_id: 'myDoc',
_attachments: {
'foo.pdf': {
length: 20,
content_type: 'application/pdf'
},
'bar.html': {
length: 15,
content_type: 'text/html'
},
'baz.foo': {
length: 5,
content_type: 'text/bar'
}
},
type: 'dynamicAttachmentsDoc',
attachmentsEnabled: true,
maximumIndividualSize: 15,
maximumTotalSize: 30,
maximumAttachmentCount: 2,
supportedExtensions,
supportedContentTypes,
requireAttachmentReferences: true,
attachmentReferences: [ 'foo.pdf', 'bar.html' ],
filenameRegexPattern: filenameRegexString
};
testFixture.verifyDocumentNotCreated(
doc,
'dynamicAttachmentsDoc',
[
errorFormatter.requireAttachmentReferencesViolation('baz.foo'),
errorFormatter.maximumIndividualAttachmentSizeViolation('foo.pdf', 15),
errorFormatter.maximumTotalAttachmentSizeViolation(30),
errorFormatter.maximumAttachmentCountViolation(2),
errorFormatter.supportedExtensionsRawAttachmentViolation('bar.html', supportedExtensions),
errorFormatter.supportedContentTypesRawAttachmentViolation('baz.foo', supportedContentTypes),
errorFormatter.attachmentFilenameRegexPatternViolation('foo.pdf', new RegExp(filenameRegexString))
]);
});
it('should block creation of a document that does not allow attachments at all', () => {
const doc = {
_id: 'myDoc',
_attachments: {
'foo.bar': {
length: 199,
content_type: 'text/plain'
}
},
type: 'dynamicAttachmentsDoc',
attachmentsEnabled: false,
requireAttachmentReferences: false
};
testFixture.verifyDocumentNotCreated(doc, 'dynamicAttachmentsDoc', [ errorFormatter.allowAttachmentsViolation() ]);
});
});
});