1 /*jshint trailing:true, white:true, indent:2, strict:true, curly:true,
2 immed:true, eqeqeq:true, forin:true, latedef:true,
3 newcap:true, noarg:true, undef:true */
4 /*global XT:true, XM:true, XV:true, exports:true, describe:true, it:true,
5 require:true, __dirname:true, console:true */
8 // i.e.: A XM.ShipVia object can not be deleted if it has been assigned as the default customer ship via in sales settings.
10 // TODO: test defaults
15 var crud = require('./crud'),
16 smoke = require('./smoke'),
17 _ = require("underscore"),
18 path = require('path'),
19 assert = require("chai").assert,
20 zombieAuth = require("./zombie_auth");
22 var runSpec = function (specContents) {
27 var spec = specContents.spec;
29 describe(spec.recordType + " test", function () {
30 this.pending = spec.skipAll;
32 if (_.isString(spec.updatableField)) {
34 spec.updateHash[spec.updatableField] = "Test" + Math.random();
38 if (spec.skipBoilerplateTests && specContents.additionalTests) {
39 specContents.additionalTests();
41 } else if (spec.skipBoilerplateTests) {
46 // Run CRUD model tests
49 crud.runAllCrud(spec);
51 // even if we skip CRUD we have to create a model
52 it('can be loaded with a zombie session', function (done) {
53 this.timeout(40 * 1000);
54 zombieAuth.loadApp({callback: done, verbose: spec.verbose,
55 loginDataPath: spec.loginDataPath});
57 it('can be created', function () {
58 spec.model = new XM[spec.recordType.substring(3)]();
65 if (!spec.skipSmoke) {
66 smoke.runUICrud(spec);
69 if (!spec.skipModelConfig) {
71 // Verify required fields
73 if (spec.requiredAttributes) {
74 _.each(spec.requiredAttributes, function (attr) {
75 it("the " + attr + " attribute is required", function () {
76 assert.include(spec.model.requiredAttributes, attr);
84 it(spec.isLockable ? "is lockable" : "is not lockable", function () {
85 assert.equal(spec.isLockable, spec.model.lockable);
91 if (spec.instanceOf === "XM.Document") {
92 it("inherits from XM.Document", function () {
93 assert.isTrue(spec.model instanceof XM.Document);
95 } else if (spec.instanceOf === "XM.Model") {
96 it("inherits from XM.Model but not XM.Document", function () {
97 assert.isTrue(spec.model instanceof XM.Model);
98 assert.isFalse(spec.model instanceof XM.Document);
101 it("has its inheritance defined in the test spec", function () {
107 // Verify ID attribute
109 if (spec.idAttribute) {
110 it("has " + spec.idAttribute + " as its idAttribute", function () {
111 assert.equal(spec.idAttribute, spec.model.idAttribute);
114 it("has its id attribute defined in the test spec", function () {
120 // Verify Document Key
122 if (spec.documentKey) {
123 it("has " + spec.documentKey + " as its documentKey", function () {
124 assert.equal(spec.documentKey, spec.model.documentKey);
129 // Make sure we're testing the enforceUpperCase (the asserts themselves are in CRUD)
131 if (spec.enforceUpperKey) {
132 it((spec.enforceUpperKey ? "Enforces" : "Does not enforce") + " uppercasing the key", function () {
133 assert.equal(spec.model.enforceUpperKey, spec.enforceUpperKey);
135 if (!_.isBoolean(spec.enforceUpperKey)) {
136 it("has its enforceUpperKey convention defined in the test spec", function () {
145 _.each(spec.attributes, function (attr) {
146 it("contains the " + attr + " attribute", function () {
147 assert.include(spec.model.getAttributeNames(), attr);
150 if (!spec.attributes || spec.attributes.length === 0) {
151 it("has some attributes defined in the test spec", function () {
157 // Verify privileges are declared correctly by the extensions
159 _.each(spec.privileges, function (priv) {
160 if (typeof priv === 'string') {
161 _.each(spec.extensions, function (extension) {
162 it("has privilege " + priv + " declared by the " + extension + " extension", function () {
163 assert.isDefined(_.findWhere(XT.session.relevantPrivileges,
164 {privilege: priv, module: spec.relevantPrivilegeModule || extension}),
165 "Perhaps you're adding the privilege in a different module and haven't set the " +
166 "spec.relevantPrivilegeModule attribute to be that module?");
170 XXX this could get tripped up by non-core extensions
171 it("has privilege " + priv + " not declared by any other extensions", function () {
172 var matchedPriv = _.filter(XT.session.relevantPrivileges, function (sessionPriv) {
173 return sessionPriv.privilege === priv && !_.contains(spec.extensions, sessionPriv.module);
175 assert.equal(0, matchedPriv.length);
179 // Make sure the privilege is translated
181 it("has privilege " + priv + " that is translated in the strings file", function () {
182 var privLoc = "_" + XT.String.camelize(priv);
183 assert.notEqual(XT.String.loc(privLoc), privLoc);
191 _.each(spec.privileges, function (priv, key) {
193 createReadUpdateDelete: ["canCreate", "canRead", "canUpdate", "canDelete"],
194 createUpdateDelete: ["canCreate", "canUpdate", "canDelete"],
195 createUpdate: ["canCreate", "canUpdate"],
196 create: ["canCreate"],
198 update: ["canUpdate"],
199 delete: ["canDelete"]
201 pertinentMethods = methodMap[key],
202 updatePriv = spec.privileges.update ||
203 spec.privileges.createUpdate ||
204 spec.privileges.createUpdateDelete;
206 it("needs " + priv + " privilege to perform action " + key, function () {
207 var schema = XT.session.schemas.XM.get(XT.String.suffix(spec.recordType)),
208 personalPrivs = schema.privileges.personal,
209 Klass = XT.getObjectByName(spec.recordType);
212 //console.log("skipping personal");
213 // TODO: don't let personal privs mess us up. Find a way to test them.
214 } else if (_.isString(priv)) {
215 assert.isDefined(pertinentMethods); // make sure we're testing for the priv
216 XT.session.privileges.attributes[priv] = false;
217 if (key === "read" && updatePriv) {
218 // update privs are sufficient for read, so we have to toggle those too
219 XT.session.privileges.attributes[updatePriv] = false;
221 _.each(pertinentMethods, function (pertinentMethod) {
222 assert.isFalse(Klass[pertinentMethod]());
224 XT.session.privileges.attributes[priv] = true;
225 if (key === "read" && updatePriv) {
226 // update privs are sufficient for read, so we have to toggle those too
227 XT.session.privileges.attributes[updatePriv] = true;
229 _.each(pertinentMethods, function (pertinentMethod) {
230 assert.isTrue(Klass[pertinentMethod]());
233 } else if (_.isBoolean(priv)) {
234 _.each(pertinentMethods, function (pertinentMethod) {
235 assert.equal(Klass[pertinentMethod](), priv);
239 it("has privilege " + priv + " that's a string or boolean in the test spec", function () {
247 // Test that the collection exists
249 if (spec.collectionType) {
250 it("backs the " + spec.collectionType + " collection", function () {
251 var Collection = XT.getObjectByName(spec.collectionType),
252 modelPrototype = Collection.prototype.model.prototype,
253 editableModel = modelPrototype.editableModel || modelPrototype.recordType;
255 assert.isFunction(Collection);
256 assert.equal(editableModel, spec.recordType);
258 } else if (spec.collectionType === null) {
259 // TODO: loop through the existing collections and make sure that
260 // none are backed by spec.recordType
262 it("has no colletion specified in the test spec", function () {
268 // Test that the cache exists
270 if (spec.cacheName) {
271 it("is cached as " + spec.cacheName, function () {
272 var cache = XT.getObjectByName(spec.cacheName);
273 assert.isObject(cache);
274 assert.equal(cache.model.prototype.recordType, spec.recordType);
277 } else if (spec.cacheName === null) {
279 TODO: probably the best thing to do is to loop through the caches and make sure
280 that none of them are backed by spec.recordType
281 it("is not cached", function () {
286 it("has a cache (or null for no cache) specified in the test spec", function () {
292 // TODO: verify that the cache is made available by certain extensions and not others
293 // TODO: verify that the list is made available by certain extensions and not others
295 if (specContents.additionalTests) {
296 specContents.additionalTests();
298 if (specContents.extensionTests) {
299 specContents.extensionTests();
305 exports.runSpec = runSpec;