<commit_before>/**
 * Unit tests for couchdb-model
 */

var should = require('chai').should();
var couchDBModel = require('../lib/couchdb-model.js'); 
var createNano = require('nano');
var extend = require('node.extend');
var Q = require('q');

var COUCHDB_BASE_URL = process.env.COUCHDB_BASE_URL;
if (!COUCHDB_BASE_URL) {
	throw new Error(
		'$COUCHDB_BASE_URL environment variable is not set. ' + 
		'Please provide a working couchdb base URL to run the tests.');
}

var COUCHDB_DB_NAME = process.env.COUCHDB_DB_NAME || 'couchdb-model-test';

var nano = createNano(COUCHDB_BASE_URL);

describe('couchdb-model', function() {
	beforeEach(function(done) {
		nano.db.destroy(COUCHDB_DB_NAME, function() {
			nano.db.create(COUCHDB_DB_NAME, function(error) {
				if (error) throw error;
				done();
			});
		});
	});

	it('should create a model from a nano database handler', function() {
		var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));
	});

	describe.skip('simple model with ID indexing', function() {

		it('should create a model with ID', 
			function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			var instance = Model.create({
				_id: 'test-id',
				value: 'hello'
			});

			instance.save(function(error) {
				if (error) throw error;
				Model.findOneByID('test-id', function(error, result) {
					if (error) throw error;
					instance.toVO().should.deep.equal(result.toVO());
					done();
				});
			});
		});

		it('should create a model with automatic ID', function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			var instance = Model.create({
				value: 'hello'
			});

			instance.save(function(error) {
				if (error) throw error;
				Model.findOneByID(instance._id, function(error, result) {
					if (error) throw error;
					instance.toVO().should.deep.equal(result.toVO());
					done();
				});
			});
		});

		it('should update an instance correctly', function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			var instance = Model.create({
				value: 'hello'
			});

			instance.save(function(error) {
				if (error) throw error;
				Model.findOneByID(instance._id, function(error, result) {
					if (error) throw error;
					instance.toVO().should.deep.equal(result.toVO());

					instance.value = 'goodbye';
					instance.save(function(error) {
						if (error) throw error;
						Model.findOneByID(instance._id, 
						function(error, result) {
							if (error) throw error;
							result.toVO().should.deep.equal(instance.toVO());
							done();
						});
					});
				});
			});
		});

		it('should delete an instance', function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			var instance = Model.create({
				value: 'hello'
			});

			instance.save(function(error) {
				if (error) throw error;
				var id = instance._id;
				instance.delete(function(error) {
					if (error) throw error;
					Model.findOneByID(id, function(error, data) {
						error.should.be.an('object');
						should.not.exist(data);		
						done();
					});
				});
			});
		});

		it('should allow to override the constructor', function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			Model.instanceConstructor = function (model, data) {
				couchDBModel.Instance.call(this, model, data);
				// Instance constructor already applied all field in 'data' to 'this'.
				this.passwordWithAnX = 'X' + this.password;	// bulletproof encryption
				this.password = <PASSWORD>;
			};

			extend(Model.instanceConstructor.prototype, couchDBModel.Instance.prototype, {
				checkPassword: function(password) {
					return this.passwordWithAnX === 'X' + password;
				}
			});

			var user = Model.create({ username: 'username', password: 'pw'});

			user.should.be.instanceof(Model.instanceConstructor);
			should.not.exist(user.password);

			user.save(function(error) {
				Model.findOneByID(user._id, function(error, result) {
					result.should.be.instanceof(Model.instanceConstructor);
					should.not.exist(user.password);
					user.passwordWithAnX.should.be.ok;
					user.checkPassword('pw').should.be.ok;
					user.checkPassword('<PASSWORD>').should.be.not.ok;
					done();
				});
			});	

		});
	});

	describe('model with views', function() {
		var db = nano.use(COUCHDB_DB_NAME);
		var model, dd, articles;
		// create test design document in the database
		beforeEach(function(done) {
			this.timeout(10000);

			dd = {
				_id: '_design/article',
				views: {
					by_date: {
						map: function(doc) {
							emit(doc.postDate, doc);
						}
					},
					by_tag: {
						map: function(doc) {
							if (Array.isArray(doc.tags)) {
								doc.tags.forEach(function(e) {
									emit(e, doc);
								});
							}
						}
					},
					by_slug: {
						map: function(doc) {
							emit(doc.slug, doc);
						}
					}
				}
			};

			model = new couchDBModel(db, {
				views: [
					'_design/article/_view/by_date',
					{
						url: '_design/article/view/by_tag',
						name: 'by_one_of_the_tags'
					},
					{
						url: '_design/article/view/by_slug'
					}
				]
			});

			// test data
			articles = [
				model.create({
					_id: '0',
					date: "1970-01-01T00:00:00",
					slug: "test_article_that_is_super_old",
					tags: []
				}),
				model.create({
					_id: '1',<commit_msg>removed unnecessary new<commit_after>/**
 * Unit tests for couchdb-model
 */

var should = require('chai').should();
var couchDBModel = require('../lib/couchdb-model.js'); 
var createNano = require('nano');
var extend = require('node.extend');
var Q = require('q');

var COUCHDB_BASE_URL = process.env.COUCHDB_BASE_URL;
if (!COUCHDB_BASE_URL) {
	throw new Error(
		'$COUCHDB_BASE_URL environment variable is not set. ' + 
		'Please provide a working couchdb base URL to run the tests.');
}

var COUCHDB_DB_NAME = process.env.COUCHDB_DB_NAME || 'couchdb-model-test';

var nano = createNano(COUCHDB_BASE_URL);

describe('couchdb-model', function() {
	beforeEach(function(done) {
		nano.db.destroy(COUCHDB_DB_NAME, function() {
			nano.db.create(COUCHDB_DB_NAME, function(error) {
				if (error) throw error;
				done();
			});
		});
	});

	it('should create a model from a nano database handler', function() {
		var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));
	});

	describe.skip('simple model with ID indexing', function() {

		it('should create a model with ID', 
			function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			var instance = Model.create({
				_id: 'test-id',
				value: 'hello'
			});

			instance.save(function(error) {
				if (error) throw error;
				Model.findOneByID('test-id', function(error, result) {
					if (error) throw error;
					instance.toVO().should.deep.equal(result.toVO());
					done();
				});
			});
		});

		it('should create a model with automatic ID', function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			var instance = Model.create({
				value: 'hello'
			});

			instance.save(function(error) {
				if (error) throw error;
				Model.findOneByID(instance._id, function(error, result) {
					if (error) throw error;
					instance.toVO().should.deep.equal(result.toVO());
					done();
				});
			});
		});

		it('should update an instance correctly', function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			var instance = Model.create({
				value: 'hello'
			});

			instance.save(function(error) {
				if (error) throw error;
				Model.findOneByID(instance._id, function(error, result) {
					if (error) throw error;
					instance.toVO().should.deep.equal(result.toVO());

					instance.value = 'goodbye';
					instance.save(function(error) {
						if (error) throw error;
						Model.findOneByID(instance._id, 
						function(error, result) {
							if (error) throw error;
							result.toVO().should.deep.equal(instance.toVO());
							done();
						});
					});
				});
			});
		});

		it('should delete an instance', function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			var instance = Model.create({
				value: 'hello'
			});

			instance.save(function(error) {
				if (error) throw error;
				var id = instance._id;
				instance.delete(function(error) {
					if (error) throw error;
					Model.findOneByID(id, function(error, data) {
						error.should.be.an('object');
						should.not.exist(data);		
						done();
					});
				});
			});
		});

		it('should allow to override the constructor', function(done) {
			var Model = couchDBModel(nano.use(COUCHDB_DB_NAME));

			Model.instanceConstructor = function (model, data) {
				couchDBModel.Instance.call(this, model, data);
				// Instance constructor already applied all field in 'data' to 'this'.
				this.passwordWithAnX = 'X' + this.password;	// bulletproof encryption
				this.password = <PASSWORD>;
			};

			extend(Model.instanceConstructor.prototype, couchDBModel.Instance.prototype, {
				checkPassword: function(password) {
					return this.passwordWithAnX === 'X' + password;
				}
			});

			var user = Model.create({ username: 'username', password: 'pw'});

			user.should.be.instanceof(Model.instanceConstructor);
			should.not.exist(user.password);

			user.save(function(error) {
				Model.findOneByID(user._id, function(error, result) {
					result.should.be.instanceof(Model.instanceConstructor);
					should.not.exist(user.password);
					user.passwordWithAnX.should.be.ok;
					user.checkPassword('pw').should.be.ok;
					user.checkPassword('<PASSWORD>').should.be.not.ok;
					done();
				});
			});	

		});
	});

	describe('model with views', function() {
		var db = nano.use(COUCHDB_DB_NAME);
		var model, dd, articles;
		// create test design document in the database
		beforeEach(function(done) {
			this.timeout(10000);

			dd = {
				_id: '_design/article',
				views: {
					by_date: {
						map: function(doc) {
							emit(doc.postDate, doc);
						}
					},
					by_tag: {
						map: function(doc) {
							if (Array.isArray(doc.tags)) {
								doc.tags.forEach(function(e) {
									emit(e, doc);
								});
							}
						}
					},
					by_slug: {
						map: function(doc) {
							emit(doc.slug, doc);
						}
					}
				}
			};

			model = couchDBModel(db, {
				views: [
					'_design/article/_view/by_date',
					{
						url: '_design/article/view/by_tag',
						name: 'by_one_of_the_tags'
					},
					{
						url: '_design/article/view/by_slug'
					}
				]
			});

			// test data
			articles = [
				model.create({
					_id: '0',
					date: "1970-01-01T00:00:00",
					slug: "test_article_that_is_super_old",
					tags: []
				}),
				model.create({
					_id: '1',
{'fraction_non_alphanumeric': 0.15348310364357184, 'fraction_numerical': 0.0039645082121955826, 'mean_word_length': 2.9681647940074907, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7030118', 'n_tokens_mistral': 4648, 'n_tokens_neox': 3562, 'n_words': 694}