public void SynchronizeAction_LFDataDeleted_EntryRemoved()
        {
            // Setup
            TestEnvironment.CopyFwProjectTo(testProjectCode, _lDSettings.WebWorkDirectory);

            _lfProject.IsInitialClone = true;
            _transferFdoToMongo.Run(_lfProject);

            IEnumerable<LfLexEntry> originalMongoData = _mongoConnection.GetLfLexEntries();
            LfLexEntry lfEntry = originalMongoData.First(e => e.Guid == _testEntryGuid);
            DateTime originalLfDateModified = lfEntry.DateModified;

            string unchangedGloss = lfEntry.Senses[0].Gloss["en"].Value;

            // Don't use _mongoConnection.RemoveRecord to delete the entry.  LF uses the "IsDeleted" field
            lfEntry.IsDeleted = true;
            // The LF PHP code would have updated DateModified when it deleted the record, so simulate that here
            lfEntry.DateModified = DateTime.UtcNow;
            _mongoConnection.UpdateRecord(_lfProject, lfEntry);
            IEnumerable<LfLexEntry> updatedMongoData = _mongoConnection.GetLfLexEntries();
            Assert.That(updatedMongoData.First(e => e.Guid == _testEntryGuid).IsDeleted, Is.True);

            _lDProject = new LanguageDepotMock(_lDSettings, testProjectCode);
            var lDcache = _lDProject.FieldWorksProject.Cache;
            var lDFdoEntry = lDcache.ServiceLocator.GetObject(_testEntryGuid) as ILexEntry;
            Assert.That(lDFdoEntry.SensesOS[0].Gloss.AnalysisDefaultWritingSystem.Text, Is.EqualTo(unchangedGloss));
            DateTime originalLdDateModified = lDFdoEntry.DateModified;

            // Exercise
            var sutSynchronize = new SynchronizeAction(_env.Settings, _env.Logger);
            sutSynchronize.Run(_lfProject);

            // Verify
            IEnumerable<LfLexEntry> receivedMongoData = _mongoConnection.GetLfLexEntries();
            Assert.That(receivedMongoData, Is.Not.Null);
            Assert.That(receivedMongoData, Is.Not.Empty);
            // Deleting entries in LF should *not* remove them, just set the isDeleted flag
            Assert.That(receivedMongoData.Count(), Is.EqualTo(originalNumOfFdoEntries));
            var entry = receivedMongoData.FirstOrDefault(e => e.Guid ==_testEntryGuid);
            Assert.That(entry, Is.Not.Null);
            Assert.That(entry.IsDeleted, Is.EqualTo(true));
            DateTime updatedLfDateModified = entry.DateModified;
            Assert.That(updatedLfDateModified, Is.GreaterThan(originalLfDateModified));
            Assert.That(updatedLfDateModified, Is.GreaterThan(originalLdDateModified));

            var cache = _lfProject.FieldWorksProject.Cache;
            Assert.That(()=> cache.ServiceLocator.GetObject(_testEntryGuid),
                Throws.InstanceOf<KeyNotFoundException>());
        }
        public void SynchronizeAction_LFDataDeletedLDDataChanged_LDWins()
        {
            // Setup
            TestEnvironment.CopyFwProjectTo(modifiedTestProjectCode, _lDSettings.WebWorkDirectory);
            Directory.Move(Path.Combine(_lDSettings.WebWorkDirectory, modifiedTestProjectCode), LDProjectFolderPath);

            _lfProject.IsInitialClone = true;
            _transferFdoToMongo.Run(_lfProject);

            IEnumerable<LfLexEntry> originalMongoData = _mongoConnection.GetLfLexEntries();
            LfLexEntry lfEntry = originalMongoData.First(e => e.Guid == _testEntryGuid);
            DateTime originalLfDateModified = lfEntry.DateModified;

            string unchangedGloss = lfEntry.Senses[0].Gloss["en"].Value;
            string fwChangedGloss = unchangedGloss + " - changed in FW";

            // Don't use _mongoConnection.RemoveRecord to delete the entry.  LF uses the "IsDeleted" field
            lfEntry.IsDeleted = true;
            _mongoConnection.UpdateRecord(_lfProject, lfEntry);
            IEnumerable<LfLexEntry> updatedMongoData = _mongoConnection.GetLfLexEntries();
            Assert.That(updatedMongoData.First(e => e.Guid == _testEntryGuid).IsDeleted, Is.True);

            _lDProject = new LanguageDepotMock(_lDSettings, testProjectCode);
            var lDcache = _lDProject.FieldWorksProject.Cache;
            var lDFdoEntry = lDcache.ServiceLocator.GetObject(_testEntryGuid) as ILexEntry;
            Assert.That(lDFdoEntry.SensesOS[0].Gloss.AnalysisDefaultWritingSystem.Text, Is.EqualTo(fwChangedGloss));
            DateTime originalLdDateModified = lDFdoEntry.DateModified;

            // Exercise
            var sutSynchronize = new SynchronizeAction(_env.Settings, _env.Logger);
            sutSynchronize.Run(_lfProject);

            // Verify LD modified entry remains and LF marks not deleted
            Assert.That(GetGlossFromMongoDb(_testEntryGuid), Is.EqualTo(fwChangedGloss));
            Assert.That(GetGlossFromLanguageDepot(_testEntryGuid, 2), Is.EqualTo(fwChangedGloss));
            LfLexEntry updatedLfEntry = _mongoConnection.GetLfLexEntries().First(e => e.Guid == _testEntryGuid);
            DateTime updatedLfDateModified = updatedLfEntry.DateModified;
            Assert.That(updatedLfDateModified, Is.GreaterThan(originalLfDateModified));
            Assert.That(updatedLfDateModified, Is.GreaterThan(originalLdDateModified));
        }
        public void SynchronizeAction_LFDataChangedLDDataDeleted_LFWins()
        {
            // Setup
            TestEnvironment.CopyFwProjectTo(modifiedTestProjectCode, _lDSettings.WebWorkDirectory);
            Directory.Move(Path.Combine(_lDSettings.WebWorkDirectory, modifiedTestProjectCode), LDProjectFolderPath);

            _lfProject.IsInitialClone = true;
            _transferFdoToMongo.Run(_lfProject);

            IEnumerable<LfLexEntry> originalMongoData = _mongoConnection.GetLfLexEntries();
            LfLexEntry lfEntry = originalMongoData.First(e => e.Guid == _testDeletedEntryGuid);
            DateTime originalLfDateModified = lfEntry.DateModified;
            Assert.That(lfEntry.Senses.Count, Is.EqualTo(1));
            const string lfCreatedGloss = "new English gloss - added in LF";
            const string fwChangedGloss = "English gloss - changed in FW";
            // LF adds a gloss to the entry that LD is deleting
            lfEntry.Senses[0].Gloss = LfMultiText.FromSingleStringMapping("en", lfCreatedGloss);
            _mongoConnection.UpdateRecord(_lfProject, lfEntry);

            _lDProject = new LanguageDepotMock(_lDSettings, testProjectCode);
            var lDcache = _lDProject.FieldWorksProject.Cache;
            Assert.That(()=> lDcache.ServiceLocator.GetObject(_testDeletedEntryGuid),
                Throws.InstanceOf<KeyNotFoundException>());
            var lDFdoEntry = lDcache.ServiceLocator.GetObject(_testEntryGuid) as ILexEntry;
            Assert.That(lDFdoEntry.SensesOS[0].Gloss.AnalysisDefaultWritingSystem.Text, Is.EqualTo(fwChangedGloss));
            DateTime originalLdDateModified = lDFdoEntry.DateModified;

            // Exercise
            var sutSynchronize = new SynchronizeAction(_env.Settings, _env.Logger);
            sutSynchronize.Run(_lfProject);

            // Verify modified LF entry wins
            Assert.That(GetGlossFromMongoDb(_testDeletedEntryGuid, originalNumOfFdoEntries + 1, 0),
                Is.EqualTo(lfCreatedGloss));
            Assert.That(GetGlossFromMongoDb(_testEntryGuid, originalNumOfFdoEntries + 1, 0),
                Is.EqualTo(fwChangedGloss));
            Assert.That(GetGlossFromLanguageDepot(_testDeletedEntryGuid, 1), Is.EqualTo(lfCreatedGloss));
            LfLexEntry updatedLfEntry = _mongoConnection.GetLfLexEntries().First(e => e.Guid == _testEntryGuid);
            DateTime updatedLfDateModified = updatedLfEntry.DateModified;
            Assert.That(updatedLfDateModified, Is.GreaterThan(originalLfDateModified));
            Assert.That(updatedLfDateModified, Is.GreaterThan(originalLdDateModified));
        }
        public void SynchronizeAction_LFDataChanged_GlossChanged()
        {
            // Setup
            TestEnvironment.CopyFwProjectTo(testProjectCode, _lDSettings.WebWorkDirectory);

            _lfProject.IsInitialClone = true;
            _transferFdoToMongo.Run(_lfProject);
            IEnumerable<LfLexEntry> originalMongoData = _mongoConnection.GetLfLexEntries();
            LfLexEntry lfEntry = originalMongoData.First(e => e.Guid == _testEntryGuid);
            string unchangedGloss = lfEntry.Senses[0].Gloss["en"].Value;
            string lfChangedGloss = unchangedGloss + " - changed in LF";
            lfEntry.Senses[0].Gloss["en"].Value = lfChangedGloss;
            _mongoConnection.UpdateRecord(_lfProject, lfEntry);

            _lDProject = new LanguageDepotMock(_lDSettings, testProjectCode);
            var lDcache = _lDProject.FieldWorksProject.Cache;
            var lDFdoEntry = lDcache.ServiceLocator.GetObject(_testEntryGuid) as ILexEntry;
            Assert.That(lDFdoEntry, Is.Not.Null);
            Assert.That(lDFdoEntry.SensesOS.Count, Is.EqualTo(2));
            Assert.That(lDFdoEntry.SensesOS[0].Gloss.AnalysisDefaultWritingSystem.Text, Is.EqualTo(unchangedGloss));

            // Exercise
            var sutSynchronize = new SynchronizeAction(_env.Settings, _env.Logger);
            sutSynchronize.Run(_lfProject);

            // Verify
            Assert.That(GetGlossFromFdo(_testEntryGuid, 2), Is.EqualTo(lfChangedGloss));
            Assert.That(GetGlossFromMongoDb(_testEntryGuid, expectedDeletedEntries: 0),
                Is.EqualTo(lfChangedGloss));
            Assert.That(GetGlossFromLanguageDepot(_testEntryGuid, 2), Is.EqualTo(lfChangedGloss));
        }
        public void SynchronizeAction_LDDataChanged_GlossChanged()
        {
            // Setup
            TestEnvironment.CopyFwProjectTo(modifiedTestProjectCode, _lDSettings.WebWorkDirectory);
            Directory.Move(Path.Combine(_lDSettings.WebWorkDirectory, modifiedTestProjectCode), LDProjectFolderPath);

            _lfProject.IsInitialClone = true;
            _transferFdoToMongo.Run(_lfProject);
            IEnumerable<LfLexEntry> originalMongoData = _mongoConnection.GetLfLexEntries();
            LfLexEntry lfEntry = originalMongoData.First(e => e.Guid == _testEntryGuid);
            string unchangedGloss = lfEntry.Senses[0].Gloss["en"].Value;
            string ldChangedGloss = unchangedGloss + " - changed in FW";

            lfEntry = originalMongoData.First(e => e.Guid == _testDeletedEntryGuid);
            Assert.That(lfEntry.Lexeme["qaa-x-kal"].Value, Is.EqualTo("ken"));

            int createdEntryCount = originalMongoData.Count(e => e.Guid == _testCreatedEntryGuid);
            Assert.That(createdEntryCount, Is.EqualTo(0));

            _lDProject = new LanguageDepotMock(_lDSettings, testProjectCode);
            var lDcache = _lDProject.FieldWorksProject.Cache;
            var lDFdoEntry = lDcache.ServiceLocator.GetObject(_testEntryGuid) as ILexEntry;
            Assert.That(lDFdoEntry.SensesOS[0].Gloss.AnalysisDefaultWritingSystem.Text, Is.EqualTo(ldChangedGloss));

            // Exercise
            var sutSynchronize = new SynchronizeAction(_env.Settings, _env.Logger);
            sutSynchronize.Run(_lfProject);

            // Verify
            Assert.That(GetGlossFromFdo(_testEntryGuid, 2), Is.EqualTo(ldChangedGloss));
            Assert.That(GetGlossFromMongoDb(_testEntryGuid), Is.EqualTo(ldChangedGloss));

            IEnumerable<LfLexEntry> receivedMongoData = _mongoConnection.GetLfLexEntries();
            lfEntry = receivedMongoData.First(e => e.Guid == _testCreatedEntryGuid);
            Assert.That(lfEntry.Lexeme["qaa-x-kal"].Value, Is.EqualTo("Ira"));

            int deletedEntryCount = receivedMongoData.Count(e => e.Guid == _testDeletedEntryGuid && !e.IsDeleted);
            Assert.That(deletedEntryCount, Is.EqualTo(0));

            Assert.That(GetGlossFromLanguageDepot(_testEntryGuid, 2), Is.EqualTo(ldChangedGloss));
        }