/// <summary> /// Compares a given activity to the list of activities specified by IgnoringActivities list in the test configuration. /// </summary> /// <param name="activity">An activity that the client received from the bot.</param> /// <returns>true if the activity matches one of the activities in the list. Otherwise returns false.</returns> public bool IgnoreActivity(Activity activity) { bool ignore = false; if (this.ignoreActivitiesList != null) { foreach (Activity activityToIgnore in this.ignoreActivitiesList) { string activityToIgnoreSerializedJson = JsonConvert.SerializeObject(activityToIgnore, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); string activitySerializedJson = JsonConvert.SerializeObject(activity, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); JObject activityToIgnoreJObject = JsonConvert.DeserializeObject <JObject>(activityToIgnoreSerializedJson); JObject activityJObject = JsonConvert.DeserializeObject <JObject>(activitySerializedJson); DialogResult.ActivityMismatchCount = 0; if (DialogResult.CompareJObjects(activityToIgnoreJObject, activityJObject) == 0) { Trace.TraceInformation($"Bot-reply activity matched IgnoreActivities[{this.ignoreActivitiesList.IndexOf(activityToIgnore)}]. Ignore it."); ignore = true; break; } } } return(ignore); }
/// <summary> /// Sends a message activity to the bot after wrapping a message in an Activity object. /// </summary> /// <param name="message">Utterance text in each turn.</param> /// <returns>Activity.</returns> public async Task <BotConnector> Send(string message) { IMessageActivity bfActivity = Activity.CreateMessageActivity(); bfActivity.Text = message; string jsonConnectorActivity = JsonConvert.SerializeObject(bfActivity); return(await this.SendActivity(jsonConnectorActivity).ConfigureAwait(false)); }
/// <summary> /// Method to get Expected TTS Audio Response Duration corresponding to an Expected Response Text that matches Actual Response Text. /// </summary> /// <param name="expectedResponse">Expected Bot response activity.</param> /// <param name="actualResponse">Bot response activity.</param> /// <param name="expectedTTSAudioResponseDuration">Expected TTS Audio Response Duration that might be separated by OR operator.</param> private static int GetCorrespondingExpectedTTSAudioResponseDuration(Activity expectedResponse, Activity actualResponse, string expectedTTSAudioResponseDuration) { string normalizedExpectedText = GetNormalizedText(expectedResponse.Text); string normalizedActualText = GetNormalizedText(actualResponse.Text); if (normalizedExpectedText.Contains(ProgramConstants.OROperator, StringComparison.OrdinalIgnoreCase)) { int i = normalizedExpectedText.Split(ProgramConstants.OROperator).ToList().IndexOf(normalizedActualText); return(Convert.ToInt32(expectedTTSAudioResponseDuration.Split(ProgramConstants.OROperator)[i], CultureInfo.InvariantCulture)); } else { return(Convert.ToInt32(expectedTTSAudioResponseDuration, CultureInfo.InvariantCulture)); } }
/// <summary> /// Checks for proper, valid input combination of the dialog turns. /// </summary> /// <param name="turn">A turn object.</param> /// <param name="botGreeting">Bot greeting value from the application settings.</param> /// <param name="singleConnection">Single connection value from the test settings.</param> /// <param name="firstDialog">true if this is the first dialog in the test file.</param> /// <param name="firstTurn">true if this is the first turn in the dialog.</param> /// <returns>A tuple of a boolean and a list of strings. The boolean is set to true if the string is valid and the list of strings captures the error messages if the turn is not valid.</returns> private static (bool ValidTurn, List <string> ExceptionMesssage) ValidateTurnInput(Turn turn, bool botGreeting, bool singleConnection, bool firstDialog, bool firstTurn) { bool utterancePresentValid = CheckNotNullNotEmptyString(turn.Utterance); bool activityPresentValid = CheckNotNullNotEmptyString(turn.Activity); bool wavFilePresentValid = CheckNotNullNotEmptyString(turn.WAVFile); bool expectedLatencyPresentValid = CheckNotNullNotEmptyString(turn.ExpectedUserPerceivedLatency); List <string> exceptionMessage = new List <string>(); if (activityPresentValid) { var(activityObjectValid, errorMsg) = CheckValidActivity(turn.Activity); if (!activityObjectValid) { exceptionMessage.Add(errorMsg); } } if (expectedLatencyPresentValid) { if (turn.ExpectedResponses != null && turn.ExpectedResponses.Count != 0) { var expectedLatencyObjectValid = CheckValidExpectedLatency(turn.ExpectedUserPerceivedLatency, turn.ExpectedResponses.Count); if (!expectedLatencyObjectValid) { exceptionMessage.Add(ErrorStrings.LATENCY_STRING_MALFORMED); } } else { exceptionMessage.Add(ErrorStrings.LATENCY_STRING_PRESENT); } } if (turn.ExpectedResponses != null && turn.ExpectedResponses.Count != 0 && turn.ExpectedTTSAudioResponseDurations != null) { if (turn.ExpectedTTSAudioResponseDurations.Count != turn.ExpectedResponses.Count) { exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_INVALID); } else { for (int i = 0; i < turn.ExpectedResponses.Count; i++) { Activity expectedResponse = turn.ExpectedResponses[i]; int orsInText = (expectedResponse.Text == null) ? 0 : expectedResponse.Text.Split(ProgramConstants.OROperator).Length - 1; int orsInSpeak = (expectedResponse.Speak == null) ? 0 : expectedResponse.Speak.Split(ProgramConstants.OROperator).Length - 1; int orsInExpectedTTSAudioResponseDuration = turn.ExpectedTTSAudioResponseDurations[i].Split(ProgramConstants.OROperator).Length - 1; if (orsInText != orsInSpeak || orsInSpeak != orsInExpectedTTSAudioResponseDuration) { exceptionMessage.Add(ErrorStrings.OR_OCCURRENCE_INCONSISTENT); } } if (!CheckValidExpectedTTSAudioDuration(turn.ExpectedTTSAudioResponseDurations)) { exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_VALUES_INVALID); } } } if ((turn.ExpectedResponses == null || turn.ExpectedResponses.Count == 0) && turn.ExpectedTTSAudioResponseDurations != null) { exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_PRESENT); } if (utterancePresentValid && wavFilePresentValid && activityPresentValid) { exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.ALL_PRESENT}"); } if (wavFilePresentValid && !utterancePresentValid && activityPresentValid) { exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.WAV_FILE_ACTIVITY_PRESENT}"); } if (utterancePresentValid && !wavFilePresentValid && activityPresentValid) { exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.UTTERANCE_ACTIVITY_PRESENT}"); } // By default, assume there should be an input ("Utterance", "Activity" or "WAVFile") bool inputExpected = true; // Change the default for the case where a turn checking bot greeting is expected. For bot greeting, there should be no input. if (botGreeting && firstTurn && ((firstDialog && singleConnection) || !singleConnection)) { inputExpected = false; } // Does the current dialog have input? bool inputPresent = utterancePresentValid || wavFilePresentValid || activityPresentValid; if (inputExpected && !inputPresent) { // There should have been an input specified ("Utterance", "Activity" or "WAVFile"), but there are none. That's an error. exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.NONE_PRESENT}"); } if (!inputExpected && inputPresent) { // There is an input specified ("Utterance", "Activity" or "WAVFile"), but there should be no input. That's an error exceptionMessage.Add(ErrorStrings.BOT_GREETING_MISSING); } if (turn.Sleep < 0) { // Sleep duration in msec - The value should be non-negative exceptionMessage.Add(ErrorStrings.NEGATIVE_SLEEP_DURATION); } if (exceptionMessage.Count > 0) { return(false, exceptionMessage); } return(true, exceptionMessage); }