public void Test21_FwAddsEntryCAndComment([ValueSource(typeof(ModelVersionValue), nameof(ModelVersionValue.GetValues))] int dbVersion)
        {
            // Setup
            _FieldWorks.ApplyPatches(dbVersion, 7);
            _webwork.ApplyPatches(dbVersion, 6);
            _LanguageForge.RestoreDatabase(dbVersion, 6);

            // Exercise
            LfMergeHelper.Run($"--project {Settings.DbName} --action=Synchronize");

            // Verify
            Assert.That(TestHelper.SRState, Is.EqualTo("IDLE"));

            // language=json
            const string expected = @"[ { 'lexicon': [
				{ 'lexeme': { 'fr' : { 'value' : 'B' } },
					'senses' : [ {
						'definition' : { 'en' : { 'value' : 'B' } }
				} ] },
				{ 'lexeme': { 'fr' : { 'value' : 'C' } },
					'senses' : [ {
						/* no definition */
						'gloss' : { 'en' : { 'value' : 'C' } }
				} ] },
				{ 'lexeme': { 'fr' : { 'value' : 'A' } },
					'senses' : [ {
						/* no definition */
						'gloss' : { 'en' : { 'value' : 'A' } }
				} ] }
			]}, { 'notes': [
				{ 'class' : 'question',
					'ref' : 'A',
					'messages': [
						{ 'message' : {
						'status': '',
						'value': 'FW comment on word A'
					}}]
				}, { 'class' : 'question',
					'ref' : 'B',
					'messages': [
					{ 'message' : {
						'status': 'open',
						'value': 'Comment on word B'
					}}]
				}, { 'class' : 'question',
					'ref' : 'C',
					'messages': [
					{ 'message' : {
						'status': '',
						'value': 'Comment about new word C'
					}}]
				}
			]}]"            ;

            VerifyMongo.AssertData(expected);

            var expectedXml = JsonToXml.Convert(expected);

            VerifyLanguageDepot.AssertFilesContain(expectedXml);
        }
        public void EditWinsOverDelete([ValueSource(typeof(ModelVersionValue), nameof(ModelVersionValue.GetValues))] int dbVersion)
        {
            // Setup
            _mongo.RestoreDatabase(dbVersion, 4);
            _languageDepot.ApplyPatches(dbVersion, 4);
            _webWork.ApplyPatches(dbVersion, 3);

            // Exercise
            LfMergeHelper.Run($"--project {Settings.DbName} --action=Synchronize");

            // Verify
            Assert.That(TestHelper.SRState, Is.EqualTo("IDLE"));

            // language=json
            const string expected = @"[ { 'lexicon': [
				{ 'lexeme': { 'fr' : { 'value' : 'lf1modified' } },
					'senses' : [ {
						'definition' : { 'en' : { 'value' : 'Word added by LF' } },
						'partOfSpeech' : { 'value' : 'n1' }
					} ] },
				{ 'lexeme': { 'fr' : { 'value' : 'flexmodified' } },
					'senses' : [ {
						/* no definition */
						'gloss' : { 'en' : { 'value' : 'created in FLEx' } },
						'partOfSpeech' : { 'value' : 'adv1' }
					} ] },
				]}]"                ;

            VerifyMongo.AssertData(expected);

            var expectedXml = JsonToXml.Convert(expected);

            VerifyLanguageDepot.AssertFilesContain(expectedXml);
        }
        public void Test11_LfAddsCommentOnF_FwResolves_LfReopens([ValueSource(typeof(ModelVersionValue), nameof(ModelVersionValue.GetValues))] int dbVersion)
        {
            // Setup
            _webwork.ApplyPatches(dbVersion, 25);
            _LanguageForge.RestoreDatabase(dbVersion, 26);
            _FieldWorks.ApplyPatches(dbVersion, 25);

            // Exercise
            LfMergeHelper.Run($"--project {Settings.DbName} --action=Synchronize");

            // Verify
            Assert.That(TestHelper.SRState, Is.EqualTo("IDLE"));

            var expected = $"[ {{ 'notes': [ {CommentsA_D}, {CommentE}, " +
                           // language=json
                           @"{ 'class' : 'question',
				'ref' : 'F',
				'messages': [
					{ 'message' : {
						'status': 'open',
						'value': 'LF comment on F'
					}}, { 'message': {
						'status': 'resolved'
					}}, { 'message': {
						'status': 'open'
					}}
				] }
			]}]"            ;

            VerifyMongo.AssertData(expected);

            var expectedXml = JsonToXml.Convert(expected);

            VerifyLanguageDepot.AssertFilesContain(expectedXml);
        }
        public void ResolvedCommentsMixedWithReplies()
        {
            // language=json
            var json = @"[ { 'notes': [
				{ 'class' : 'question',
				'ref' : 'E',
					'messages': [
						{ 'message' : {
							'status': '',
							'value': 'FW comment on E'
						} },
						{ 'message': {
							'status': 'open',
							'value': 'LF reply on E'
						} },
						{ 'message': {
							'status': 'resolved'
						} }
				]}]}]"                ;

            var xElement = JsonToXml.Convert(json);

            VerifyTree(xElement, XElement.Parse(
                           // language=xml
                           @"<root>
	<notes>
		<annotation class=""question"" ref=""label=E"">
			<message status="""">FW comment on E</message>
			<message status=""open"">LF reply on E</message>
			<message status=""closed""/>
		</annotation>
	</notes>
</root>"));
        }
        public void Test08_FwAddsCommentOnA_LfAddsCommentOnB_LfSyncsFirst([ValueSource(typeof(ModelVersionValue), nameof(ModelVersionValue.GetValues))] int dbVersion)
        {
            // Setup
            _webwork.ApplyPatches(dbVersion, 4);
            // apply patch 6 without 4
            _webwork.ApplySinglePatch(dbVersion, 6, false);
            _webwork.RemoveNodeFromFile("Lexicon.fwstub.ChorusNotes",
                                        "/notes/annotation[message='FW comment on word A']",
                                        "Patch 6 without 4 (Add comment on B)");
            _FieldWorks.ApplyPatches(dbVersion, 4);
            _FieldWorks.MergeWith(_webwork);

            _LanguageForge.RestoreDatabase(dbVersion, 5);

            // Exercise
            LfMergeHelper.Run($"--project {Settings.DbName} --action=Synchronize");

            // Verify
            Assert.That(TestHelper.SRState, Is.EqualTo("IDLE"));

            // language=json
            const string expected = @"[ { 'lexicon': [
				{ 'lexeme': { 'fr' : { 'value' : 'B' } },
					'senses' : [ {
						'definition' : { 'en' : { 'value' : 'B' } }
					} ] },
				{ 'lexeme': { 'fr' : { 'value' : 'A' } },
					'senses' : [ {
						/* no definition */
						'gloss' : { 'en' : { 'value' : 'A' } }
					} ] }
			]}, { 'notes': [
				{ 'class' : 'question',
					'ref' : 'B',
					'messages': [
						{'message' : {
						'status': 'open',
						'value': 'Comment on word B'
					}}]
				}, { 'class' : 'question',
					'ref' : 'A',
					'messages': [
						{'message' : {
						'status': '',
						'value': 'FW comment on word A'
					}}]
				}
			]}]"            ;

            VerifyMongo.AssertData(expected);

            var expectedXml = JsonToXml.Convert(expected);

            VerifyLanguageDepot.AssertFilesContain(expectedXml);
        }
        public void Test09a_FwAddsCommentOnE_LfReplies([ValueSource(typeof(ModelVersionValue), nameof(ModelVersionValue.GetValues))] int dbVersion)
        {
            // Setup
            _webwork.ApplyPatches(dbVersion, 17);
            _FieldWorks.ApplyPatches(dbVersion, 17);
            _LanguageForge.RestoreDatabase(dbVersion, 18);

            // Exercise
            LfMergeHelper.Run($"--project {Settings.DbName} --action=Synchronize");

            // Verify
            Assert.That(TestHelper.SRState, Is.EqualTo("IDLE"));

            // NOTE: although Chorus stores a status on every comment when we have replies,
            // only the last status determines the overall status of the comment!

            var expected = $"[ {{ 'notes': [ {CommentsA_D}, " +
                           // language=json
                           @"{ 'class' : 'question',
				'ref' : 'E',
				'messages': [
					{'message' : {
						'status': '',
						'value': 'FW comment on E'
					} },
					{ 'message': {
						'status': 'open',
						'value': 'LF reply on E'
					} }
				] }
			]}]"            ;

            VerifyMongo.AssertData(expected);

            var expectedXml = JsonToXml.Convert(expected);

            VerifyLanguageDepot.AssertFilesContain(expectedXml);
        }
        public void LexiconDataOnly()
        {
            // language=json
            var json = @"[ { 'lexicon': [
			{ 'lexeme': { 'fr1' : { 'value' : 'B1' } },
				'senses' : [ {
					'definition' : { 'en1' : { 'value' : 'Bdef2' } },
					'gloss' : { 'en2' : { 'value' : '' } }
				} ] },
			{ 'lexeme': { 'fr2' : { 'value' : 'A3' } },
				'senses' : [ {
					/* no definition */
					'gloss' : { 'en3' : { 'value' : 'Agloss4' } }
				} ] }
			]}]"            ;

            var xElement = JsonToXml.Convert(json);

            VerifyTree(xElement, XElement.Parse(
// language=xml
                           @"<root>
	<Lexicon>
		<LexEntry>
			<LexemeForm>
				<MoStemAllomorph>
					<Form>
						<AUni ws=""fr1"">B1</AUni>
					</Form>
				</MoStemAllomorph>
			</LexemeForm>
			<Senses>
				<ownseq>
					<Definition>
						<AStr ws=""en1"">
							<Run ws=""en1"">Bdef2</Run>
						</AStr>
					</Definition>
					<Gloss expectAbsence=""true"" />
				</ownseq>
			</Senses>
		</LexEntry>
		<LexEntry>
			<LexemeForm>
				<MoStemAllomorph>
					<Form>
						<AUni ws=""fr2"">A3</AUni>
					</Form>
				</MoStemAllomorph>
			</LexemeForm>
			<Senses>
				<ownseq>
					<Definition expectAbsence=""true"" />
					<Gloss>
						<AUni ws=""en3"">Agloss4</AUni>
					</Gloss>
				</ownseq>
			</Senses>
		</LexEntry>
	</Lexicon>
</root>"));
        }
 public void EmptyObject()
 {
     Assert.That(() => JsonToXml.Convert("{}"),
                 Throws.TypeOf <InvalidDataException>().With.Property("Message")
                 .EqualTo("JSON data doesn't have an array as outermost element"));
 }
        public void EmptyArray()
        {
            var xElement = JsonToXml.Convert("[]");

            VerifyTree(xElement, XElement.Parse("<root/>"));
        }
        public void LexiconPlusComments()
        {
            // language=json
            var json = @"[ { 'lexicon': [
			{ 'lexeme': { 'fr1' : { 'value' : 'B1' } },
				'senses' : [ {
					'definition' : { 'en1' : { 'value' : 'Bdef2' } },
					'gloss' : { 'en2' : { 'value' : '' } }
				} ] },
			{ 'lexeme': { 'fr2' : { 'value' : 'A3' } },
				'senses' : [ {
					/* no definition */
					'gloss' : { 'en3' : { 'value' : 'Agloss4' } }
				} ] }
			]}, { 'notes': [ {
				'class' : 'question' ,
				'ref' : 'A3',
				'messages': [
				{'message' : {
					'status': 'open',
					'value': 'comment about word A'
				}}]
			}]}]"            ;

            var xElement = JsonToXml.Convert(json);

            VerifyTree(xElement, XElement.Parse(
// language=xml
                           @"<root>
	<Lexicon>
		<LexEntry>
			<LexemeForm>
				<MoStemAllomorph>
					<Form>
						<AUni ws=""fr1"">B1</AUni>
					</Form>
				</MoStemAllomorph>
			</LexemeForm>
			<Senses>
				<ownseq>
					<Definition>
						<AStr ws=""en1"">
							<Run ws=""en1"">Bdef2</Run>
						</AStr>
					</Definition>
					<Gloss expectAbsence=""true"" />
				</ownseq>
			</Senses>
		</LexEntry>
		<LexEntry>
			<LexemeForm>
				<MoStemAllomorph>
					<Form>
						<AUni ws=""fr2"">A3</AUni>
					</Form>
				</MoStemAllomorph>
			</LexemeForm>
			<Senses>
				<ownseq>
					<Definition expectAbsence=""true"" />
					<Gloss>
						<AUni ws=""en3"">Agloss4</AUni>
					</Gloss>
				</ownseq>
			</Senses>
		</LexEntry>
	</Lexicon>
	<notes>
		<annotation class=""question"" ref=""label=A3"">
			<message status=""open"">comment about word A</message>
		</annotation>
	</notes>
</root>"));
        }