|  | 
| 1 |  | -// These tests check that the Schema operates correctly. | 
| 2 | 1 | var Config = require('../src/Config'); | 
| 3 | 2 | var Schema = require('../src/Schema'); | 
| 4 | 3 | var dd = require('deep-diff'); | 
| 5 | 4 | 
 | 
| 6 | 5 | var config = new Config('test'); | 
| 7 | 6 | 
 | 
|  | 7 | +var hasAllPODobject = () => { | 
|  | 8 | +  var obj = new Parse.Object('HasAllPOD'); | 
|  | 9 | +  obj.set('aNumber', 5); | 
|  | 10 | +  obj.set('aString', 'string'); | 
|  | 11 | +  obj.set('aBool', true); | 
|  | 12 | +  obj.set('aDate', new Date()); | 
|  | 13 | +  obj.set('aObject', {k1: 'value', k2: true, k3: 5}); | 
|  | 14 | +  obj.set('aArray', ['contents', true, 5]); | 
|  | 15 | +  obj.set('aGeoPoint', new Parse.GeoPoint({latitude: 0, longitude: 0})); | 
|  | 16 | +  obj.set('aFile', new Parse.File('f.txt', { base64: 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE=' })); | 
|  | 17 | +  var objACL = new Parse.ACL(); | 
|  | 18 | +  objACL.setPublicWriteAccess(false); | 
|  | 19 | +  obj.setACL(objACL); | 
|  | 20 | +  return obj; | 
|  | 21 | +}; | 
|  | 22 | + | 
| 8 | 23 | describe('Schema', () => { | 
| 9 | 24 |   it('can validate one object', (done) => { | 
| 10 | 25 |     config.database.loadSchema().then((schema) => { | 
| @@ -406,4 +421,153 @@ describe('Schema', () => { | 
| 406 | 421 |       done(); | 
| 407 | 422 |     }); | 
| 408 | 423 |   }); | 
|  | 424 | + | 
|  | 425 | +  it('can check if a class exists', done => { | 
|  | 426 | +    config.database.loadSchema() | 
|  | 427 | +    .then(schema => { | 
|  | 428 | +      return schema.addClassIfNotExists('NewClass', {}) | 
|  | 429 | +      .then(() => { | 
|  | 430 | +        schema.hasClass('NewClass') | 
|  | 431 | +        .then(hasClass => { | 
|  | 432 | +          expect(hasClass).toEqual(true); | 
|  | 433 | +          done(); | 
|  | 434 | +        }) | 
|  | 435 | +        .catch(fail); | 
|  | 436 | + | 
|  | 437 | +        schema.hasClass('NonexistantClass') | 
|  | 438 | +        .then(hasClass => { | 
|  | 439 | +          expect(hasClass).toEqual(false); | 
|  | 440 | +          done(); | 
|  | 441 | +        }) | 
|  | 442 | +        .catch(fail); | 
|  | 443 | +      }) | 
|  | 444 | +      .catch(error => { | 
|  | 445 | +        fail('Couldn\'t create class'); | 
|  | 446 | +        fail(error); | 
|  | 447 | +      }); | 
|  | 448 | +    }) | 
|  | 449 | +    .catch(error => fail('Couldn\'t load schema')); | 
|  | 450 | +  }); | 
|  | 451 | + | 
|  | 452 | +  it('refuses to delete fields from invalid class names', done => { | 
|  | 453 | +    config.database.loadSchema() | 
|  | 454 | +    .then(schema => schema.deleteField('fieldName', 'invalid class name')) | 
|  | 455 | +    .catch(error => { | 
|  | 456 | +      expect(error.code).toEqual(Parse.Error.INVALID_CLASS_NAME); | 
|  | 457 | +      done(); | 
|  | 458 | +    }); | 
|  | 459 | +  }); | 
|  | 460 | + | 
|  | 461 | +  it('refuses to delete invalid fields', done => { | 
|  | 462 | +    config.database.loadSchema() | 
|  | 463 | +    .then(schema => schema.deleteField('invalid field name', 'ValidClassName')) | 
|  | 464 | +    .catch(error => { | 
|  | 465 | +      expect(error.code).toEqual(Parse.Error.INVALID_KEY_NAME); | 
|  | 466 | +      done(); | 
|  | 467 | +    }); | 
|  | 468 | +  }); | 
|  | 469 | + | 
|  | 470 | +  it('refuses to delete the default fields', done => { | 
|  | 471 | +    config.database.loadSchema() | 
|  | 472 | +    .then(schema => schema.deleteField('installationId', '_Installation')) | 
|  | 473 | +    .catch(error => { | 
|  | 474 | +      expect(error.code).toEqual(136); | 
|  | 475 | +      expect(error.error).toEqual('field installationId cannot be changed'); | 
|  | 476 | +      done(); | 
|  | 477 | +    }); | 
|  | 478 | +  }); | 
|  | 479 | + | 
|  | 480 | +  it('refuses to delete fields from nonexistant classes', done => { | 
|  | 481 | +    config.database.loadSchema() | 
|  | 482 | +    .then(schema => schema.deleteField('field', 'NoClass')) | 
|  | 483 | +    .catch(error => { | 
|  | 484 | +      expect(error.code).toEqual(Parse.Error.INVALID_CLASS_NAME); | 
|  | 485 | +      expect(error.error).toEqual('class NoClass does not exist'); | 
|  | 486 | +      done(); | 
|  | 487 | +    }); | 
|  | 488 | +  }); | 
|  | 489 | + | 
|  | 490 | +  it('refuses to delete fields that dont exist', done => { | 
|  | 491 | +    hasAllPODobject().save() | 
|  | 492 | +    .then(() => config.database.loadSchema()) | 
|  | 493 | +    .then(schema => schema.deleteField('missingField', 'HasAllPOD')) | 
|  | 494 | +    .fail(error => { | 
|  | 495 | +      expect(error.code).toEqual(255); | 
|  | 496 | +      expect(error.error).toEqual('field missingField does not exist, cannot delete'); | 
|  | 497 | +      done(); | 
|  | 498 | +    }); | 
|  | 499 | +  }); | 
|  | 500 | + | 
|  | 501 | +  it('drops related collection when deleting relation field', done => { | 
|  | 502 | +    var obj1 = hasAllPODobject(); | 
|  | 503 | +    obj1.save() | 
|  | 504 | +    .then(savedObj1 => { | 
|  | 505 | +      var obj2 = new Parse.Object('HasPointersAndRelations'); | 
|  | 506 | +      obj2.set('aPointer', savedObj1); | 
|  | 507 | +      var relation = obj2.relation('aRelation'); | 
|  | 508 | +      relation.add(obj1); | 
|  | 509 | +      return obj2.save(); | 
|  | 510 | +    }) | 
|  | 511 | +    .then(() => { | 
|  | 512 | +      config.database.db.collection('test__Join:aRelation:HasPointersAndRelations', { strict: true }, (err, coll) => { | 
|  | 513 | +        expect(err).toEqual(null); | 
|  | 514 | +        config.database.loadSchema() | 
|  | 515 | +        .then(schema => schema.deleteField('aRelation', 'HasPointersAndRelations', config.database.db, 'test_')) | 
|  | 516 | +        .then(() => config.database.db.collection('test__Join:aRelation:HasPointersAndRelations', { strict: true }, (err, coll) => { | 
|  | 517 | +          expect(err).not.toEqual(null); | 
|  | 518 | +          done(); | 
|  | 519 | +        })) | 
|  | 520 | +      }); | 
|  | 521 | +    }) | 
|  | 522 | +  }); | 
|  | 523 | + | 
|  | 524 | +  it('can delete string fields and resave as number field', done => { | 
|  | 525 | +    Parse.Object.disableSingleInstance(); | 
|  | 526 | +    var obj1 = hasAllPODobject(); | 
|  | 527 | +    var obj2 = hasAllPODobject(); | 
|  | 528 | +    var p = Parse.Object.saveAll([obj1, obj2]) | 
|  | 529 | +    .then(() => config.database.loadSchema()) | 
|  | 530 | +    .then(schema => schema.deleteField('aString', 'HasAllPOD', config.database.db, 'test_')) | 
|  | 531 | +    .then(() => new Parse.Query('HasAllPOD').get(obj1.id)) | 
|  | 532 | +    .then(obj1Reloaded => { | 
|  | 533 | +      expect(obj1Reloaded.get('aString')).toEqual(undefined); | 
|  | 534 | +      obj1Reloaded.set('aString', ['not a string', 'this time']); | 
|  | 535 | +      obj1Reloaded.save() | 
|  | 536 | +      .then(obj1reloadedAgain => { | 
|  | 537 | +        expect(obj1reloadedAgain.get('aString')).toEqual(['not a string', 'this time']); | 
|  | 538 | +        return new Parse.Query('HasAllPOD').get(obj2.id); | 
|  | 539 | +      }) | 
|  | 540 | +      .then(obj2reloaded => { | 
|  | 541 | +        expect(obj2reloaded.get('aString')).toEqual(undefined); | 
|  | 542 | +        done(); | 
|  | 543 | +        Parse.Object.enableSingleInstance(); | 
|  | 544 | +      }); | 
|  | 545 | +    }) | 
|  | 546 | +  }); | 
|  | 547 | + | 
|  | 548 | +  it('can delete pointer fields and resave as string', done => { | 
|  | 549 | +    Parse.Object.disableSingleInstance(); | 
|  | 550 | +    var obj1 = new Parse.Object('NewClass'); | 
|  | 551 | +    obj1.save() | 
|  | 552 | +    .then(() => { | 
|  | 553 | +      obj1.set('aPointer', obj1); | 
|  | 554 | +      return obj1.save(); | 
|  | 555 | +    }) | 
|  | 556 | +    .then(obj1 => { | 
|  | 557 | +      expect(obj1.get('aPointer').id).toEqual(obj1.id); | 
|  | 558 | +    }) | 
|  | 559 | +    .then(() => config.database.loadSchema()) | 
|  | 560 | +    .then(schema => schema.deleteField('aPointer', 'NewClass', config.database.db, 'test_')) | 
|  | 561 | +    .then(() => new Parse.Query('NewClass').get(obj1.id)) | 
|  | 562 | +    .then(obj1 => { | 
|  | 563 | +      expect(obj1.get('aPointer')).toEqual(undefined); | 
|  | 564 | +      obj1.set('aPointer', 'Now a string'); | 
|  | 565 | +      return obj1.save(); | 
|  | 566 | +    }) | 
|  | 567 | +    .then(obj1 => { | 
|  | 568 | +      expect(obj1.get('aPointer')).toEqual('Now a string'); | 
|  | 569 | +      done(); | 
|  | 570 | +      Parse.Object.enableSingleInstance(); | 
|  | 571 | +    }); | 
|  | 572 | +  }); | 
| 409 | 573 | }); | 
0 commit comments