Added 3 new LUIS auth keys
Found more of my code that needed the autoformating finished.
This commit is contained in:
Michael Skowronski 2019-12-24 16:25:57 -08:00 коммит произвёл GitHub
Родитель 0d69dda5ba
Коммит 8bf0e2ca47
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
23 изменённых файлов: 281 добавлений и 271 удалений

Просмотреть файл

@ -10,6 +10,9 @@ const authoringKeys = [
process.env.LUIS_AUTHORING_KEY_ALT_9,
process.env.LUIS_AUTHORING_KEY_ALT_10,
process.env.LUIS_AUTHORING_KEY_ALT_11,
process.env.LUIS_AUTHORING_KEY_ALT_12,
process.env.LUIS_AUTHORING_KEY_ALT_13,
process.env.LUIS_AUTHORING_KEY_ALT_14,
]
let buildNumber = +process.env.CIRCLE_BUILD_NUM
@ -17,13 +20,14 @@ let buildNumber = +process.env.CIRCLE_BUILD_NUM
// We have 11 LUIS Authoring Keys that we rotate through.
// We use the Circle CI Build Number to help us get an index to each in sequence.
// Each time a build workflow is kicked off there are 3 jobs:
// Each time a build workflow is kicked off there multiple workflow jobs:
// 1) the actual build
// 2) the smoke test run
// 3) the regression test run
// ...others like 'deploy' and whatever might be new as of recently
// The two test jobs will each consume the resources of one of our authoring keys.
// The actual build job will NOT consume the resources of one of our authoring keys, but
// The other jobs will NOT consume the resources of one of our authoring keys, but
// that is okay since as we cycle through the list of authoring keys the next time through
// the previously unused keys will get used and different authoring keys will go unused.
@ -31,10 +35,13 @@ let authoringKeyIndex = Math.floor(buildNumber % authoringKeys.length)
let luisAuthoringKey = authoringKeys[authoringKeyIndex]
// Because of the math used in the algorithm above, the number of authoring keys should
// not be divisible by 3, otherwise 1 out of every 3 keys will rarely get used.
// be a prime number, otherwise there is a chance that some keys will get used all the time
// while others are not used. Also there should be enough keys so that at least 4 full runs
// can complete before it begins reusing keys.
//
// There are other things can influence the next build number to be used, like if the
// build fails, then the other two jobs won't run so only 1 build number
// will be consumed.
// will be consumed, but that is factored into the algorithm.
console.log(`export LUIS_AUTHORING_KEY=${luisAuthoringKey}\n`)

Просмотреть файл

@ -1,6 +1,6 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
* Licensed under the MIT License.
*/
import * as popupModal from './PopupModal'
@ -18,7 +18,7 @@ export function ClickCancelDeleteButton() { popupModal.VerifyExactTitleNoContent
// TODO: VERIFY EVERY TEST THAT USES THIS...AND THEN FIX THE CANCEL VERSION AS WELL!!!
export function ClickConfirmDeleteWithWarningButton() { popupModal.VerifyExactTitleAndContentContainsClickButton('Are you sure you want to delete this Action?', 'This Action is used by one or more Training Dialogs.', '[data-testid="action-delete-confirm"]') }
//popupModal.VerifyContentAnyTitleClickButton('This Action is used by one or more Training Dialogs.', '[data-testid="confirm-cancel-modal-accept"]') }
//popupModal.VerifyContentAnyTitleClickButton('This Action is used by one or more Training Dialogs.', '[data-testid="confirm-cancel-modal-accept"]') }
export function ClickCancelDeleteWithWarningButton() { popupModal.VerifyContentAnyTitleClickButton('This Action is used by one or more Training Dialogs.', '[data-testid="confirm-cancel-modal-cancel"]') }
export function ClickTrainDialogFilterButton() { cy.Get('[data-testid="action-creator-editor-train-dialog-filter-button"]').Click() }
@ -35,7 +35,7 @@ export function TypeCardLine3(line) { TypeInField('[data-testid="action-card-arg
export function TypeCardButton1(buttonText) { TypeInField('[data-testid="action-card-argument-button1"] div[data-slate-editor="true"]', buttonText) }
export function TypeCardButton2(buttonText) { TypeInField('[data-testid="action-card-argument-button2"] div[data-slate-editor="true"]', buttonText) }
function TypeInField(fieldSelector, text) {
function TypeInField(fieldSelector, text) {
cy.Get(fieldSelector).clear().type(text)
ClickOnNoOpHack()
}
@ -45,8 +45,7 @@ export function VerifyActionTypeDisabled() { cy.Get('[aria-disabled="true"][data
export function VerifyErrorMessage(expectedMessage) { cy.Get('[data-testid="action-creator-editor-error-callback"]').ExactMatch(expectedMessage) }
function SelectFromDropdown(selector, option)
{
function SelectFromDropdown(selector, option) {
cy.Get(selector).Click()
cy.Get('button.ms-Dropdown-item').ExactMatch(option).Click()
}
@ -63,11 +62,11 @@ export function TypeResponse(textToType) {
export function TypeApiLogicArgs(args) { TypeApiArgs('Logic Arguments', args) }
export function TypeApiRenderArgs(args) { TypeApiArgs('Render Arguments', args) }
function ClickOnNoOpHack() {
function ClickOnNoOpHack() {
// This has no effect on the data in this Action Modal but it some how
// resets something in the UI that enables picking an entity.
// Bug 2132: TEST BLOCKER: Automation cannot trigger 2nd Entity picker in API Action arguments
cy.get('[data-testid="action-creator-wait-checkbox"]').click()
cy.get('[data-testid="action-creator-wait-checkbox"]').click()
}
function TypeApiArgs(apiArgLabel, args) {
@ -142,7 +141,7 @@ export function RemoveExpectedEntity(entityName) { RemoveEntityOrCondition('acti
export function RemoveRequiredCondition(entityNameOrCondition) { RemoveEntityOrCondition('action-required-entities', entityNameOrCondition) }
export function RemoveDisqualifyingCondition(entityNameOrCondition) { RemoveEntityOrCondition('action-disqualifying-entities', entityNameOrCondition) }
function RemoveEntityOrCondition(dataTestId, entityNameOrCondition) {
function RemoveEntityOrCondition(dataTestId, entityNameOrCondition) {
cy.Get(`[data-testid="${dataTestId}"]`)
.find('[data-testid="tag-item"]')
// We need 'contains' here as well as 'ExactMatch' because it returns a single element

Просмотреть файл

@ -1,20 +1,20 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
* Licensed under the MIT License.
*/
export const pairs = [
{type: 'TEXT', selector: '[data-testid="action-scorer-text-response"]'},
{type: 'API', selector: '[data-testid="action-scorer-api"]'},
{type: 'END_SESSION', selector: '[data-testid="action-scorer-session-response-user"]'},
{type: 'CARD', selector: '[data-testid="action-scorer-card"]'},
{type: 'SET_ENTITY', selector: '[data-testid="actions-list-set-entity"], [data-testid="action-scorer-action-set-entity"]'},
{type: 'MISSING ACTION', selector: '[data-testid="action-scorer-action-set-entity"]'},
{ type: 'TEXT', selector: '[data-testid="action-scorer-text-response"]' },
{ type: 'API', selector: '[data-testid="action-scorer-api"]' },
{ type: 'END_SESSION', selector: '[data-testid="action-scorer-session-response-user"]' },
{ type: 'CARD', selector: '[data-testid="action-scorer-card"]' },
{ type: 'SET_ENTITY', selector: '[data-testid="actions-list-set-entity"], [data-testid="action-scorer-action-set-entity"]' },
{ type: 'MISSING ACTION', selector: '[data-testid="action-scorer-action-set-entity"]' },
]
export function GetSelector(actionType) {
let typeSelectorPair = pairs.find(typeSelectorPair => typeSelectorPair.type === actionType)
export function GetSelector(actionType) {
let typeSelectorPair = pairs.find(typeSelectorPair => typeSelectorPair.type === actionType)
if (!typeSelectorPair) { throw new Error(`Test Code Error - Unrecognized type: '${actionType}'`) }
return typeSelectorPair.selector
}

Просмотреть файл

@ -1,6 +1,6 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
* Licensed under the MIT License.
*/
import * as actionTypeSelector from '../../support/components/ActionTypeSelector'
@ -29,19 +29,19 @@ export class Row {
}
EditAction() { cy.Get('@responseDetailsRow').Click() }
VerifyActionType(actionType) {cy.Get('@responseDetailsRow').find('[data-testid="action-details-action-type"]').ExactMatch(actionType)}
VerifyActionType(actionType) { cy.Get('@responseDetailsRow').find('[data-testid="action-details-action-type"]').ExactMatch(actionType) }
VerifyExpectedEntity(entity) { this._VerifyEntities('[data-testid="action-details-expected-entity"]', '[data-testid="action-details-empty-expected-entity"]', entity) }
// The UI automatically populates the Required Entities field with entities found in the response text,
// so the additionalRequiredEntities parameter allows the caller to specify entities not found in the response text.
VerifyRequiredEntities(requiredEntitiesFromResponse, additionalRequiredEntities) { this._VerifyEntities('[data-testid="action-details-required-entities"]', '[data-testid="action-details-empty-required-entities"]', requiredEntitiesFromResponse, additionalRequiredEntities) }
// The UI automatically populates the Disqualtifying Entities field with the expected entity,
// so the disqualifyingEntities parameter allows the caller to specify entities not found in expectedEntity.
VerifyDisqualifyingEntities(expectedEntity, disqualifyingEntities) { this._VerifyEntities('[data-testid="action-details-disqualifying-entities"]', '[data-testid="action-details-empty-disqualifying-entities"]', expectedEntity, disqualifyingEntities) }
VerifyIncidentTriangle() { cy.Get('@responseDetailsRow').find('[data-icon-name="IncidentTriangle"]') }
VerifyWaitForResponse(checked) { cy.Get('@responseDetailsRow').find(`[data-icon-name="${checked ? 'CheckMark' : 'Remove'}"][data-testid="action-details-wait"]`) }
@ -53,7 +53,7 @@ export class Row {
if (!entities1 && !entities2) return this._VerifyEntitiesIsEmpty(emptySelector)
let entities = []
if (entities1) {
if (entities1) {
if (!Array.isArray(entities1)) { entities = [entities1] }
else { entities = entities1 }
}
@ -87,7 +87,7 @@ export function VerifyAllActionRows(rows) {
helpers.ConLog('VerifyAllActionRows', `${row.response}, ${row.type}, ${row.requiredEntities}, ${row.disqualifyingEntities}, ${row.expectedEntity}, ${row.wait}`)
VerifyActionRow(row.response, row.type, row.requiredEntities, row.disqualifyingEntities, row.expectedEntity, row.wait)
})
const gridRowCount = Cypress.$('div[role="presentation"].ms-List-cell').length
if (gridRowCount > rows.length) {
throw new Error(`Found all of the expected Action Rows, however there are an additional ${gridRowCount - rows.length} Action Rows in the grid that we were not expecting.`)
@ -95,7 +95,7 @@ export function VerifyAllActionRows(rows) {
})
}
export function GetAllRows() {
export function GetAllRows() {
const funcName = 'GetAllRows'
helpers.ConLog(funcName, 'start')
@ -112,16 +112,16 @@ export function GetAllRows() {
let expectedEntity = helpers.TextContentWithoutNewlines(Cypress.$(allRowElements[i]).find('[data-testid="action-details-expected-entity"]')[0])
let wait = Cypress.$(allRowElements[i]).find('[data-icon-name="CheckMark"][data-testid="action-details-wait"]').length == 1
allRowData.push({
response: response,
type: type,
requiredEntities: requiredEntities,
disqualifyingEntities: disqualifyingEntities,
expectedEntity: expectedEntity,
wait: wait,
allRowData.push({
response: response,
type: type,
requiredEntities: requiredEntities,
disqualifyingEntities: disqualifyingEntities,
expectedEntity: expectedEntity,
wait: wait,
})
helpers.ConLog(funcName, `${response}, ${type}, ${requiredEntities}, ${disqualifyingEntities}, ${expectedEntity}, ${wait}`)
}
return allRowData
}

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as trainDialogsGrid from './TrainDialogsGrid'
import * as scorerModal from './ScorerModal'

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
export function VerifyPageTitle() { cy.Get('[data-testid="settings-delete-model-title"]').contains('Deletion is irreversible.').should('be.visible') }
export function ClickExportButton() { cy.Get('[data-testid="model-creator-submit-button"]').Click() }

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as helpers from '../../support/Helpers'
export function VerifyPageTitle() { cy.Get('[data-testid="entities-title"]').contains('Entities').should('be.visible') }
@ -18,14 +18,14 @@ export class Row {
}
EditEntity() { cy.Get('@entityDetailsRow').Click() }
VerifyType(type) { cy.Get('@entityDetailsRow').find('[data-testid="entities-type"]').contains(type) }
VerifyResolverType(resolverType) {
VerifyResolverType(resolverType) {
if (resolverType) { cy.Get('@entityDetailsRow').find('[data-testid="entities-resolver"]').ExactMatch(resolverType) }
else { cy.Get('@entityDetailsRow').find('[data-testid="entities-resolver-none"]') }
}
VerifyMultiValue(checked) { cy.Get('@entityDetailsRow').find(`i[data-icon-name="${checked ? 'CheckMark' : 'Remove'}"][data-testid="entities-multi-value"]`) }
VerifyNegatable(checked) { cy.Get('@entityDetailsRow').find(`i[data-icon-name="${checked ? 'CheckMark' : 'Remove'}"][data-testid="entities-negatable"]`) }
}
@ -48,7 +48,7 @@ export function VerifyAllEntityRows(rows) {
helpers.ConLog('VerifyAllEntityRows', `${row.name}, ${row.type}, ${row.resolverType}, ${row.multiValue}, ${row.negatable}`)
VerifyEntityRow(row.name, row.type, row.resolverType, row.multiValue, row.negatable)
})
const gridRowCount = Cypress.$('div[role="presentation"].ms-List-cell').length
if (gridRowCount > rows.length) {
throw new Error(`Found all of the expected Action Rows, however there are an additional ${gridRowCount - rows.length} Action Rows in the grid that we were not expecting.`)
@ -57,7 +57,7 @@ export function VerifyAllEntityRows(rows) {
}
export function GetAllRows() {
export function GetAllRows() {
helpers.ConLog('GetAllRows', 'start')
let allRowData = []
@ -81,7 +81,7 @@ export function GetAllRows() {
helpers.ConLog('GetAllRows', `${name}, ${type}, ${resolverType}, ${multiValue}, ${negatable}`)
}
return allRowData
}

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as helpers from '../Helpers'

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as popupModal from './PopupModal'
import * as helpers from '../Helpers'

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
export function VerifyPageTitle() { cy.Get('[data-testid="export-choice-title"]').contains('Export Model').should('be.visible') }
export function ClickExportButton() { cy.Get('[data-testid="model-creator-submit-button"]').Click() }

Просмотреть файл

@ -1,16 +1,16 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as modelPage from '../components/ModelPage'
import * as helpers from '../Helpers'
export function Visit() { return cy.visit('http://localhost:3000'); VerifyPageTitle() }
export function VerifyPageTitle() { return cy.Get('[data-testid="model-list-title"]').contains('Create and manage your Conversation Learner models').should('be.visible') }
export function ClickNewModelButton() { return cy.Get('[data-testid="model-list-create-new-button"]', {timeout: 10000}).Click() }
export function ClickImportModelButton() { return cy.Get('[data-testid="model-list-import-model-button"]', {timeout: 10000}).Click() }
export function TypeModelName(name) { return cy.Get('[data-testid="model-creator-input-name"]', {timeout: 10000}).type(name) }
export function ClickNewModelButton() { return cy.Get('[data-testid="model-list-create-new-button"]', { timeout: 10000 }).Click() }
export function ClickImportModelButton() { return cy.Get('[data-testid="model-list-import-model-button"]', { timeout: 10000 }).Click() }
export function TypeModelName(name) { return cy.Get('[data-testid="model-creator-input-name"]', { timeout: 10000 }).type(name) }
export function ClickSubmitButton() { return cy.Get('[data-testid="model-creator-submit-button"]').Click() }
export function UploadImportModelFile(name) { return cy.UploadFile(name, 'input[type="file"]') }
@ -29,7 +29,7 @@ export function WaitForModelListToLoad() {
// }
// })
cy.wrap(1, {timeout: 10000}).should(() => {
cy.wrap(1, { timeout: 10000 }).should(() => {
// Subtract 1 because it includes the header row.
const rowCount = +Cypress.$('[data-automationid="DetailsList"] > [role="grid"]').attr('aria-rowcount') - 1
if (rowCount == 0) {
@ -51,18 +51,18 @@ export function WaitForModelListToLoad() {
})
}
export function VerifyModelNameInList(modelName) {
export function VerifyModelNameInList(modelName) {
WaitForModelListToLoad()
cy.Get('[data-testid="model-list-model-name"]').ExactMatch(modelName)
cy.Get('[data-testid="model-list-model-name"]').ExactMatch(modelName)
}
export function VerifyModelNameIsNotInList(modelName) {
export function VerifyModelNameIsNotInList(modelName) {
WaitForModelListToLoad()
cy.DoesNotContain('[data-testid="model-list-model-name"]', modelName)
cy.DoesNotContain('[data-testid="model-list-model-name"]', modelName)
}
export function LoadModel(modelName) {
cy.Get('[data-testid="model-list-model-name"]', {timeout: 10000}).ExactMatch(modelName).Click()
export function LoadModel(modelName) {
cy.Get('[data-testid="model-list-model-name"]', { timeout: 10000 }).ExactMatch(modelName).Click()
modelPage.VerifyModelName(modelName)
}

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as popupModal from './PopupModal'
import * as helpers from '../Helpers'
@ -10,9 +10,9 @@ export function ClickDoneTestingButton() { return cy.Get('[data-testid="chat-ses
export function ClickAbandonDeleteButton() { cy.Get('[data-testid="edit-dialog-modal-abandon-delete-button"]').Click() }
export function TypeYourMessage(message) { cy.Get('input[placeholder="Type your message..."]').type(`${message}{enter}`) } // data-testid NOT possible
export function ClickSessionTimeoutButtonAndOkayThePopup() {
export function ClickSessionTimeoutButtonAndOkayThePopup() {
cy.Get('[data-testid="chat-session-modal-session-timeout-button"]').Click()
popupModal.VerifyExactTitleNoContentClickButton('The EndSession callback will be invoked on the next user input, and a new Session started', '[data-testid="confirm-cancel-modal-ok"]')
popupModal.VerifyExactTitleNoContentClickButton('The EndSession callback will be invoked on the next user input, and a new Session started', '[data-testid="confirm-cancel-modal-ok"]')
}
// This function verifies both the input message is reflected back and the response is what we are expecting.
@ -28,7 +28,7 @@ export function TypeYourMessageValidateResponse(message, expectedResponse) {
cy.WaitForStableDOM()
cy.Enqueue(() => {
let elements = Cypress.$('.wc-message-content')
indexUserMesage = elements.length
indexUserMesage = elements.length
indexBotResponse = indexUserMesage + 1
})
@ -43,12 +43,12 @@ export function TypeYourMessageValidateResponse(message, expectedResponse) {
// for this case we must do that at a later point in the test code. However, we do a quick
// validation here because we should also give the UI and backend a chance to process the
// user turn to produce the END_SESSION response.
// Bug 2196: EndSession Action in Log Dialog is causing 'Session not found' error
// I wanted to set this to 1000, but when I do this bug is triggered.
// If the bug gets fixed we can reduce this wait time.
let callItGoodTime = new Date().getTime() + 3000
expectedUtteranceCount = indexBotResponse
cy.get('.wc-message-content').should(elements => {
if (elements.length < expectedUtteranceCount) {
@ -66,13 +66,13 @@ export function TypeYourMessageValidateResponse(message, expectedResponse) {
startTime = Cypress.moment()
let expectedUtterance = message//.replace(/'/g, "")
// We allow for a long retry timeout because there have been times the Bot is either slow to respond
// or it does not respond at all and we want to know which of those errors are frequent or rare.
cy.get('.wc-message-content', { timeout: 30000 }).should('have.length', expectedUtteranceCount).then(elements =>{
cy.get('.wc-message-content', { timeout: 30000 }).should('have.length', expectedUtteranceCount).then(elements => {
let elapsedTime = Cypress.moment().diff(startTime)
helpers.ConLog(`TypeYourMessageValidateResponse(${message}, ${expectedResponse})`, `Elapsed Time for Bot's Response: ${elapsedTime}`)
cy.wrap(elements[indexUserMesage]).contains(expectedUtterance).then(() => {
if (expectedResponse) {
expectedUtterance = expectedResponse.replace(/'/g, "")

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as modelPage from './ModelPage'
import * as helpers from '../Helpers'
@ -19,12 +19,12 @@ export function GetTurnCounts() { return helpers.StringArrayFromElementText('[da
export function WaitForLogDialoGridUpdateToComplete(expectedLogDialogCount) {
const funcName = 'WaitForLogDialoGridUpdateToComplete'
cy.log(funcName, expectedLogDialogCount)
cy.WaitForStableDOM()
let renderingShouldBeCompleteTime = new Date().getTime()
cy.Get('[data-testid="log-dialogs-turns"]', {timeout: 10000})
.should(elements => {
cy.Get('[data-testid="log-dialogs-turns"]', { timeout: 10000 })
.should(elements => {
if (modelPage.IsOverlaid()) {
helpers.ConLog(funcName, 'modalPage.IsOverlaid')
renderingShouldBeCompleteTime = new Date().getTime() + 1000
@ -34,7 +34,7 @@ export function WaitForLogDialoGridUpdateToComplete(expectedLogDialogCount) {
throw new Error(`Waiting till no overlays show up for at least 1 second...retry '${funcName}'`)
}
if (elements.length != expectedLogDialogCount) {
if (elements.length != expectedLogDialogCount) {
const errorMessage = `${elements.length} rows found in the training grid, however we were expecting ${expectedLogDialogCount}`
helpers.ConLog(funcName, errorMessage)
throw new Error(errorMessage)
@ -65,17 +65,17 @@ export function VerifyListOfLogDialogs(expectedLogDialogs) {
break;
}
}
if (!found) {
helpers.ConLog(funcName, 'ERROR - NOT Found')
errors = true
}
})
if (errors) {
throw new Error('Did not find 1 or more of the expected Log Dialogs in the grid. Refer to the log file for details.')
}
if (userInputs.length > expectedLogDialogs.length) {
throw new Error(`Found all of the expected Train Dialogs, however there are an additional ${userInputs.length - expectedLogDialogs.length} Log Dialogs in the grid that we were not expecting. Refer to the log file for details.`)
}

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
export function VerifyEntityValues(entityName, entityValues) { _VerifyEntitiesInMemory(entityName, false, entityValues) }
export function VerifyDisplacedEntityValues(entityName, entityValues) { _VerifyEntitiesInMemory(entityName, false, entityValues, true) }
@ -10,11 +10,11 @@ export function VerifyDeletedEntityValues(entityName, entityValues) { _VerifyEnt
function _VerifyEntitiesInMemory(entityName, deleted, entityValues, displaced) {
let entityNameFont = '.cl-font--emphasis'
if (deleted) {
entityNameFont = '.cl-font--deleted'
entityNameFont = '.cl-font--deleted'
}
let entityValueFont = '.cl-font--emphasis'
if(deleted || displaced) {
if (deleted || displaced) {
entityValueFont = '.cl-font--deleted'
}

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as helpers from '../../support/Helpers'

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as homePage from '../../support/components/HomePage'
import * as entitiesGrid from '../../support/components/EntitiesGrid'
@ -32,14 +32,13 @@ export function VerifyErrorTriangleForTrainDialogs() { VerifyIncidentIcon(true,
export function VerifyNoWarningTriangleOnPage() { VerifyIncidentIcon(false, 'cl-color-warning') }
export function VerifyWarningTriangleForTrainDialogs() { VerifyIncidentIcon(true, 'cl-color-warning') }
function VerifyIncidentIcon(errorIconExpected, colorClassSelector)
{
function VerifyIncidentIcon(errorIconExpected, colorClassSelector) {
let funcName = `VerifyErrorIcon(${errorIconExpected})`
cy.WaitForStableDOM()
cy.wrap({ countFound: -1, timesInARowAtThisCount: 0 }, { timeout: 10000 }).should(retryInfo => {
const elements = Cypress.$(`i[data-icon-name="IncidentTriangle"].${colorClassSelector}`)
if(elements.length === retryInfo.countFound) { retryInfo.timesInARowAtThisCount ++ }
if (elements.length === retryInfo.countFound) { retryInfo.timesInARowAtThisCount++ }
else {
// The count changed since the last time we looked at this.
retryInfo.countFound = elements.length
@ -47,16 +46,16 @@ function VerifyIncidentIcon(errorIconExpected, colorClassSelector)
}
helpers.ConLog(funcName, `Number of Incident Triangles found on page: ${retryInfo.countFound} - Number of times in a row it was found: ${retryInfo.timesInARowAtThisCount}`)
if(retryInfo.timesInARowAtThisCount < 15) {
if (retryInfo.timesInARowAtThisCount < 15) {
throw new Error(`${retryInfo.timesInARowAtThisCount} times in a row we have seen ${retryInfo.countFound} incident triangles on the page, need to see it there 15 times before we can trust it won't change again.`)
}
// At this point we know that we have seen the same number of incident triangles many times in a row.
// Now we need to verify that it is in the state we expect, and if this next part fails, it will retry
// up to the time out setting to see if it changes to what we expect.
if(!errorIconExpected) {
if(elements.length > 0) {
if (!errorIconExpected) {
if (elements.length > 0) {
throw new Error(`Expected to find no Incident Triangles on the page, yet ${elements.length} were found`)
}
} else {

Просмотреть файл

@ -1,9 +1,9 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
export function VerifyExactTitleNoContentClickButton(expectedTitle, buttonSelector) {
export function VerifyExactTitleNoContentClickButton(expectedTitle, buttonSelector) {
cy.Get(buttonSelector)
.parents('div.ms-Dialog-main')
.find('p.ms-Dialog-title')
@ -13,10 +13,10 @@ export function VerifyExactTitleNoContentClickButton(expectedTitle, buttonSelect
.ExactMatch('')
.parents('div.ms-Dialog-main')
.find(buttonSelector)
.Click()
.Click()
}
export function VerifyExactTitleAndContentContainsClickButton(expectedTitle, expectedContent, buttonSelector) {
export function VerifyExactTitleAndContentContainsClickButton(expectedTitle, expectedContent, buttonSelector) {
cy.Get(buttonSelector)
.parents('div.ms-Dialog-main')
.find('p.ms-Dialog-title')
@ -26,15 +26,15 @@ export function VerifyExactTitleAndContentContainsClickButton(expectedTitle, exp
.contains(expectedContent)
.parents('div.ms-Dialog-main')
.find(buttonSelector)
.Click()
.Click()
}
export function VerifyContentAnyTitleClickButton(expectedContent, buttonSelector) {
export function VerifyContentAnyTitleClickButton(expectedContent, buttonSelector) {
cy.Get(buttonSelector)
.parents('div.ms-Dialog-main')
.find('.ms-Dialog-content')
.contains(expectedContent)
.parents('div.ms-Dialog-main')
.find(buttonSelector)
.Click()
.Click()
}

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as actionTypeSelector from '../../support/components/ActionTypeSelector'
import * as helpers from '../../support/Helpers'
@ -114,7 +114,7 @@ export class GeneratedData {
cy.writeFile(`cypress/fixtures/scoreActions/${this.dataFileName}`, this.data)
})
})
}
}
}
}
@ -148,7 +148,7 @@ export function ClickActionButon(selector, expectedData) {
const rowElementsOrErrorMessage = FindActionRowElements(selector, expectedData)
if (typeof rowElementsOrErrorMessage == 'string') { throw new Error(rowElementsOrErrorMessage) }
cy.wrap(rowElementsOrErrorMessage).find('[data-testid="action-scorer-button-clickable"]').Click()
cy.wrap(rowElementsOrErrorMessage).find('[data-testid="action-scorer-button-clickable"]').Click()
})
}
@ -158,7 +158,7 @@ export function ClickEntityValueNameToggleButon(selector, expectedData) {
const rowElementsOrErrorMessage = FindActionRowElements(selector, expectedData)
if (typeof rowElementsOrErrorMessage == 'string') { throw new Error(rowElementsOrErrorMessage) }
cy.wrap(rowElementsOrErrorMessage).find('[data-testid="action-scorer-entity-toggle"]').Click()
cy.wrap(rowElementsOrErrorMessage).find('[data-testid="action-scorer-entity-toggle"]').Click()
})
}
@ -169,7 +169,7 @@ export function VerifyActionState(rowSelector, expectedData, buttonSelector, dis
let elements = Cypress.$(rowElementsOrErrorMessage).find(buttonSelector)
if (elements.length == 0) { throw new Error(`Found ZERO elements for buttonSelector: '${buttonSelector}' from rowSelector: '${rowSelector}' with expectedData: '${expectedData}'`) }
if (elements[0].disabled != disabled) {
helpers.ConLog(funcName, `Element that should be ${disabled ? 'Disabled' : 'Enabled'} --- ${elements[0].outerHTML}`)
throw new Error(`Expected the Action Scorer Button to be ${disabled ? 'Disabled' : 'Enabled'}, but it was not.`)
@ -192,7 +192,7 @@ export function VerifyNoEnabledSelectActionButtons() {
const length = clickable.length + selected.length + addActionButton.length + addApiButton.length
if (length > 0 ) {
if (length > 0) {
throw new Error(`We are expecting to find NO enabled Action Scorer buttons, instead we found ${length} of them. See log file for details.`)
}
})
@ -215,10 +215,10 @@ export function VerifyScoreActions(expectedScoreActions, acceptableScoreDeviatio
function FindWithinAndVerify(baseElements, findCommand, verificationFunction, expectedElementCount = 1) {
const elements = eval(`Cypress.$(baseElements).${findCommand}`)
if (elements.length != expectedElementCount) {
if (elements.length != expectedElementCount) {
AccumulateErrors(`Expected to find exactly ${expectedElementCount} element(s) instead we found ${elements.length} - Selection Command: ${findCommand}`)
} else {
verificationFunction(elements)
} else {
verificationFunction(elements)
}
return elements
}
@ -227,7 +227,7 @@ export function VerifyScoreActions(expectedScoreActions, acceptableScoreDeviatio
for (let i = 0; i < expectedScoreActions.length; i++) {
expectedScoreAction = expectedScoreActions[i]
rowIndex = undefined
// This gets the row of the Score Action to validate and it also validates the response while doing so.
const rowElementsOrErrorMessage = FindActionRowElements(actionTypeSelector.GetSelector(expectedScoreAction.type), expectedScoreAction.response)
if (typeof rowElementsOrErrorMessage == 'string') {
@ -239,8 +239,8 @@ export function VerifyScoreActions(expectedScoreActions, acceptableScoreDeviatio
// We use the rowIndex only for the purpose of logging errors as a debugging aid.
rowIndex = Cypress.$(rowElement).parents('div[role="presentation"].ms-List-cell').attr('data-list-index')
// Verify the button.
FindWithinAndVerify(rowElement, `find('[data-testid^="action-scorer-button-"]')`, elements => {
const attr = elements.attr('data-testid')
@ -252,9 +252,9 @@ export function VerifyScoreActions(expectedScoreActions, acceptableScoreDeviatio
// Verify Entity Value/Name Toggle Control.
const elements = Cypress.$(rowElement).find('[data-testid="action-scorer-entity-toggle"]')
if ((elements.length == 1) !== expectedScoreAction.hasEntityValueNameToggle) {
AccumulateErrors(`Expected to find the Entity Value/Name Toggle switch to be ${expectedScoreAction.hasEntityValueNameToggle? 'present' : 'absent'}`)
AccumulateErrors(`Expected to find the Entity Value/Name Toggle switch to be ${expectedScoreAction.hasEntityValueNameToggle ? 'present' : 'absent'}`)
}
// Verify the score.
FindWithinAndVerify(rowElement, `find('[data-testid="action-scorer-score"]')`, elements => {
const score = helpers.TextContentWithoutNewlines(elements[0])
@ -275,14 +275,14 @@ export function VerifyScoreActions(expectedScoreActions, acceptableScoreDeviatio
}
})
// Verify the entities.
FindWithinAndVerify(rowElement, `find('[data-testid="action-scorer-entities"]').parent('div[role="listitem"]')`, elements => {
expectedScoreAction.entities.forEach(entity => {
FindWithinAndVerify(elements, `find('[data-testid="action-scorer-entities"]:contains("${entity.name}")')`, entityElement => {
const strikeOut = Cypress.$(entityElement).find(`del:contains("${entity.name}")`).length == 1 ? 'Strikeout' : ''
let entityQualifierState
if (entityElement.hasClass('cl-entity--match')) {
entityQualifierState = entityQualifierStateEnum.green + strikeOut
} else if (entityElement.hasClass('cl-entity--mismatch')) {
@ -290,7 +290,7 @@ export function VerifyScoreActions(expectedScoreActions, acceptableScoreDeviatio
} else {
AccumulateErrors(`Expected to find class with either 'cl-entity--match' or 'cl-entity--mismatch' but found neither. Element: ${entityElement[0].outerHTML}`)
}
if (entity.qualifierState != entityQualifierState) {
AccumulateErrors(`Expected '${entity.name}' Entity Qualifier to have State: ${entity.qualifierState} but instead found: ${entityQualifierState}`)
}
@ -298,7 +298,7 @@ export function VerifyScoreActions(expectedScoreActions, acceptableScoreDeviatio
})
}, expectedScoreAction.entities.length)
// Verify the Wait flag.
FindWithinAndVerify(rowElement, `find('[data-testid="action-scorer-wait"]')`, elements => {
const wait = elements.attr('data-icon-name') == 'CheckMark'
@ -316,8 +316,8 @@ export function VerifyScoreActions(expectedScoreActions, acceptableScoreDeviatio
}
})
}
if (errorMessages.length > 0) {throw new Error(`${errorMessages.length} Errors Detected in Action Scorer Grid - See log file for full list. --- 1st Error: ${errorMessages[0]}`)}
if (errorMessages.length > 0) { throw new Error(`${errorMessages.length} Errors Detected in Action Scorer Grid - See log file for full list. --- 1st Error: ${errorMessages[0]}`) }
})
}
@ -333,10 +333,10 @@ export function GenerateScoreActionsDataFromGrid() {
function FindWithinAndCapture(baseElements, findCommand, captureFunction, oneElementExpected = true) {
const elements = eval(`Cypress.$(baseElements).${findCommand}`)
if (oneElementExpected && elements.length != 1) {
if (oneElementExpected && elements.length != 1) {
AccumulateErrors(`Expected to find exactly 1 element instead we found ${elements.length} - Selection Command: ${findCommand}`)
} else {
captureFunction(elements)
} else {
captureFunction(elements)
}
return elements
}
@ -363,26 +363,26 @@ export function GenerateScoreActionsDataFromGrid() {
rowData.response = responseData
})
// Entity Value/Name Toggle Control.
const elements = Cypress.$(rowElement).find('[data-testid="action-scorer-entity-toggle"]')
rowData.hasEntityValueNameToggle = elements.length == 1
// Action Type.
FindWithinAndCapture(rowElement, `find('[data-testid="action-details-action-type"]')`, elements => {
const actionType = helpers.TextContentWithoutNewlines(elements[0])
rowData.type = actionType
})
// Get the score.
FindWithinAndCapture(rowElement, `find('[data-testid="action-scorer-score"]')`, elements => {
const score = helpers.TextContentWithoutNewlines(elements[0])
rowData.score = score
})
// Get the entities and their display attributes.
let entities = []
FindWithinAndCapture(rowElement, `find('[data-testid="action-scorer-entities"]').parent('div[role="listitem"]')`, elements => {
@ -392,7 +392,7 @@ export function GenerateScoreActionsDataFromGrid() {
const strikeOut = Cypress.$(elements[i]).find(`del:contains("${name}")`).length == 1 ? 'Strikeout' : ''
let entityQualifierState
const entityElement = Cypress.$(elements[i]).find('[data-testid="action-scorer-entities"]')
if (entityElement.hasClass('cl-entity--match')) {
entityQualifierState = entityQualifierStateEnum.green + strikeOut
@ -402,23 +402,23 @@ export function GenerateScoreActionsDataFromGrid() {
entityQualifierState = `ERROR - Expected to find class with either 'cl-entity--match' or 'cl-entity--mismatch' but found neither. Element: ${entityElement[0].outerHTML}`
AccumulateErrors(entityQualifierState)
}
entities.push({ name: name, qualifierState: entityQualifierState })
}
}
rowData.entities = entities
}, false)
// Get the Wait flag.
FindWithinAndCapture(rowElement, `find('[data-testid="action-scorer-wait"]')`, elements => {
const wait = elements.attr('data-icon-name') == 'CheckMark'
rowData.wait = wait
})
generatedData.push(rowData)
}
return generatedData
}
@ -428,13 +428,13 @@ export function GenerateScoreActionsDataFromGrid() {
// If there are no entities specified for the action, it still returns the text of the action.
export function GetTextWithEntityNamesFromSelectedAction() {
const elements = FindActionRowElements('[data-testid="action-scorer-button-selected"]', 'SelectedSelected')
if (typeof elements == 'string') {
throw new Error(elements)
if (typeof elements == 'string') {
throw new Error(elements)
}
const toggleElements = Cypress.$(elements).find('[data-testid="action-scorer-entity-toggle"]')
if (toggleElements.length == 1) {
toggleElements.click()
if (toggleElements.length == 1) {
toggleElements.click()
}
return cy.WaitForStableDOM().then(() => {

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
export function ClickAddInitialValueButton(entityName) { cy.Get('[data-testid="teach-session-add-initial-value"]').contains(entityName).Click() }
export function VerifyEntityValue(expectedValue) { cy.Get('[data-testid="teach-session-entity-name"]').contains(expectedValue) }

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as entitiesGrid from '../../support/components/EntitiesGrid'
import * as deleteModelModal from '../../support/components/DeleteModelModal'
@ -18,8 +18,8 @@ export function ClickCopyConfirmButton() { cy.Get('[data-testid="model-creator-s
export function TypeNewModelNameForRename(modelName) { cy.Get('[data-testid="settings-input-model-name"]').clear().type(`${modelName}{enter}`) }
export function VerifyModelName(expectedModelName) { cy.Get(`[data-testid="settings-input-model-name"][value="${expectedModelName}"]`) }
export function CheckLogConversationsCheckbox() { cy.Get('[data-testid="settings-log-conversations-checkbox"]').find('input').check({force: true}) }
export function UncheckLogConversationsCheckbox() { cy.Get('[data-testid="settings-log-conversations-checkbox"]').find('input').uncheck({force: true}) }
export function CheckLogConversationsCheckbox() { cy.Get('[data-testid="settings-log-conversations-checkbox"]').find('input').check({ force: true }) }
export function UncheckLogConversationsCheckbox() { cy.Get('[data-testid="settings-log-conversations-checkbox"]').find('input').uncheck({ force: true }) }
export function VerifyLogConversationsCheckbox(checked) { cy.Get('[data-testid="settings-log-conversations-checkbox"]').should(`${checked ? '' : 'not.'}be.checked`) }
export function ClickSaveButton() { cy.Get('[data-testid="settings-button-save"]').Click() }

Просмотреть файл

@ -1,14 +1,14 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as modelPage from './ModelPage'
import * as helpers from '../Helpers'
import * as chatPanel from './ChatPanel'
// Path to product code: ConversationLearner-UI\src\routes\Apps\App\TrainDialogs.tsx
export function VerifyPageTitle() {
export function VerifyPageTitle() {
cy.Get('[data-testid="train-dialogs-title"]').contains('Train Dialogs')
cy.Enqueue(() => {
if (modelPage.IsOverlaid()) {
@ -27,7 +27,7 @@ export function ClickReplaySelectedButton() { cy.Get('[data-testid="button-repla
export function SearchBox() { cy.Get('label[for="traindialogs-input-search"]').contains('input.ms-SearchBox-field') }
export function EntityDropDownFilter() { cy.Get('[data-testid="dropdown-filter-by-entity"]') }
export function ActionDropDownFilter() { cy.Get('[data-testid="dropdown-filter-by-action"]') }
export function ClickTraining(row) { cy.Get('[data-testid="train-dialogs-description"]').then(elements => { cy.wrap(elements[row]).Click({force: true}) }) }
export function ClickTraining(row) { cy.Get('[data-testid="train-dialogs-description"]').then(elements => { cy.wrap(elements[row]).Click({ force: true }) }) }
// These functions circumvent the Cypress retry logic by using jQuery
export function GetFirstInputs() { return helpers.StringArrayFromElementText('[data-testid="train-dialogs-first-input"]') }
@ -48,7 +48,7 @@ export function VerifyDescriptionForRow(row, description) { cy.Get(`div[data-ite
// The purpose of the TdGrid class is to find a specific row in the Train Dialog Grid and to wait till the
// Train Dialog Grid is ready before attempting to perform the find operation.
export class TdGrid {
// Public:
// Public:
// 1) Start here, do not call the constructor. This will construct an instance for you and pass it to
// the "thenDoFunction" that you pass in.
//
@ -71,7 +71,7 @@ export class TdGrid {
// We set the Cypress time out higher so that it never triggers. The intention is to run this code in a retry
// loop that will not fail, and exit after 4 seconds if we don't achieve stability. This allows the calling
// functions to log more information before throwing an error.
cy.wrap(1, {timeout: 5000}).should(() => {
cy.wrap(1, { timeout: 5000 }).should(() => {
try {
const currentTime = new Date().getTime()
if (!TdGrid.monitorIsActivated) {
@ -83,7 +83,7 @@ export class TdGrid {
TdGrid.monitorIsActivated = true
TdGrid.MonitorGrid()
}
if (TdGrid.isStable) {
helpers.ConLog(funcName, 'The Train Dialog Grid IS STABLE!')
TdGrid.monitorIsActivated = false
@ -97,22 +97,22 @@ export class TdGrid {
TdGrid.tdGrid = new TdGrid()
return
}
}
}
catch (error) {
helpers.ConLog(funcName, `Caught Errors: ${error.message}`)
}
helpers.ConLog(funcName, 'Failed attempt, the Train Dialog Grid is not stable yet.')
throw new Error(`Train Dialog Grid is not stable yet, however, if you see this in the Cypress UI it is a TEST BUG`)
// Its a test bug if this error shows up in the Cypress UI because this function was designed to NOT time out.
}).then(() => {
return thenDoFunction(TdGrid.tdGrid)
}).then(() => {
return thenDoFunction(TdGrid.tdGrid)
})
}
// 2) this should be called from an object returned from TdGrid.GetTdGrid
// Returns the index of the row that was found or -1 if not found
FindGridRowByChatInputs(firstInput, lastInput, lastResponse){
FindGridRowByChatInputs(firstInput, lastInput, lastResponse) {
const funcName = `TdGrid.FindGridRowByChatInputs("${firstInput}", "${lastInput}", "${lastResponse}")`
helpers.ConLog(funcName, this.feedback)
@ -127,7 +127,7 @@ export class TdGrid {
return i
}
}
helpers.ConLog(funcName, 'Not Found')
return -1
}
@ -135,7 +135,7 @@ export class TdGrid {
// 2) this should be called from an object returned from TdGrid.GetTdGrid
// Returns the index of the row that was found or -1 if not found
// You may provide both description and tags or just one of them.
FindGridRowByDescriptionAndOrTags(description, tagList){
FindGridRowByDescriptionAndOrTags(description, tagList) {
const funcName = `TdGrid.FindGridRowByDescriptionAndOrTags("${description}", "${tagList}")`
helpers.ConLog(funcName, this.feedback)
@ -146,7 +146,7 @@ export class TdGrid {
if (description && tagList && this.descriptions.length != this.tagLists.length) {
throw new Error(`Somethings wrong in TdGrid.FindGridRowByDescriptionAndOrTags - ${this.feedback}`)
}
const length = description ? this.descriptions.length : (tagList ? this.tagLists : undefined)
for (let i = 0; i < length; i++) {
if ((!description || this.descriptions[i] === description) && (!tagList || this.tagLists[i] == tagList)) {
@ -154,7 +154,7 @@ export class TdGrid {
return i
}
}
helpers.ConLog(funcName, 'Not Found')
return -1
}
@ -163,30 +163,30 @@ export class TdGrid {
// Returns the index of the row that was found or -1 if not found
// If firstInput is empty string it will not use any of these 3 in the search: firstInput, lastInput, lastResponse
// If either decription or tagList is an empty string it will not be used in the search.
FindGridRowByAll(firstInput, lastInput, lastResponse, description, tagList){
FindGridRowByAll(firstInput, lastInput, lastResponse, description, tagList) {
const funcName = `TdGrid.FindGridRowByAll("${firstInput}", "${lastInput}", "${lastResponse}", "${description}", "${tagList}")`
helpers.ConLog(funcName, this.feedback)
try {
if (// Since this.rowCount is derived from this.firstInputs.length we don't need to verify it.
this.rowCount != this.lastInputs.length ||
this.rowCount != this.lastResponses.length ||
this.rowCount != this.descriptions.length ||
this.rowCount != this.tagLists.length) {
throw new Error(`Somethings wrong in TdGrid.FindGridRowByAll - ${this.feedback}`)
this.rowCount != this.lastInputs.length ||
this.rowCount != this.lastResponses.length ||
this.rowCount != this.descriptions.length ||
this.rowCount != this.tagLists.length) {
throw new Error(`Somethings wrong in TdGrid.FindGridRowByAll - ${this.feedback}`)
}
for (let i = 0; i < this.firstInputs.length; i++) {
if ((!firstInput ||
(this.firstInputs[i] === firstInput &&
this.lastInputs[i] === lastInput &&
if ((!firstInput ||
(this.firstInputs[i] === firstInput &&
this.lastInputs[i] === lastInput &&
this.lastResponses[i] === lastResponse)) &&
(!description || this.descriptions[i] === description) &&
(!tagList || this.tagLists[i] === tagList)) {
(!description || this.descriptions[i] === description) &&
(!tagList || this.tagLists[i] === tagList)) {
helpers.ConLog(funcName, `Found on row ${i}`)
return i
}
}
helpers.ConLog(funcName, 'Not Found')
return -1
}
@ -198,53 +198,53 @@ export class TdGrid {
get rowCount() { return this.firstInputs.length }
get firstInputs() {
if (!this._firstInputs) {
get firstInputs() {
if (!this._firstInputs) {
this._firstInputs = GetFirstInputs()
this.feedback += ` - Length First Inputs: ${this._firstInputs.length}`
}
}
return this._firstInputs
}
get lastInputs() {
if (!this._lastInputs) {
get lastInputs() {
if (!this._lastInputs) {
this._lastInputs = GetLastInputs()
this.feedback += ` - Length Last Inputs: ${this._lastInputs.length}`
}
}
return this._lastInputs
}
get lastResponses() {
if (!this._lastResponses) {
get lastResponses() {
if (!this._lastResponses) {
this._lastResponses = GetLastResponses()
this.feedback += ` - Length Last Responses: ${this._lastResponses.length}`
}
}
return this._lastResponses
}
get descriptions() {
if (!this._descriptions) {
get descriptions() {
if (!this._descriptions) {
this._descriptions = GetDescriptions()
this.feedback += ` - Length Descriptions: ${this._descriptions.length}`
}
}
return this._descriptions
}
get tagLists() {
if (!this._tagLists) {
get tagLists() {
if (!this._tagLists) {
this._tagLists = GetTagLists()
this.feedback += ` - Length Tags: ${this._tagLists.length}`
}
return this._tagLists
}
// STATICS:
// Once CreateNewTrainDialog or one of the two EditTraining* functions are used, the Train Dialog Grid is hidden,
// it should not change, there is no need to access it again until a change is saved from the Train Dialog Editor
// and the Model page is once again the top most view.
//
// These static methods then allow for expected changes to be made to internal data that can be later used to verify
// that any changes made to Train Dialogs are reflected in the grid once it refreshes.
// STATICS:
// Once CreateNewTrainDialog or one of the two EditTraining* functions are used, the Train Dialog Grid is hidden,
// it should not change, there is no need to access it again until a change is saved from the Train Dialog Editor
// and the Model page is once again the top most view.
//
// These static methods then allow for expected changes to be made to internal data that can be later used to verify
// that any changes made to Train Dialogs are reflected in the grid once it refreshes.
static CreateNewTrainDialog(expectedRowCount = -1) {
cy.Enqueue(() => {
@ -255,38 +255,38 @@ export class TdGrid {
})
}
static EditTrainingByChatInputs(firstInput, lastInput, lastResponse, expectedRowCount = -1) {
static EditTrainingByChatInputs(firstInput, lastInput, lastResponse, expectedRowCount = -1) {
const funcName = `EditTrainingByChatInputs(${firstInput}, ${lastInput}, ${lastResponse})`
cy.Enqueue(() => {
TdGrid.GetAllRows(expectedRowCount)
}).then(() => {
let iRow = TdGrid.iCurrentRow = TdGrid.tdGrid.FindGridRowByChatInputs(firstInput, lastInput, lastResponse)
if (iRow < 0) {
if (iRow < 0) {
throw new Error(`Can't Find Training to Edit. The grid should, but does not, contain a row with this data in it: FirstInput: ${firstInput} -- LastInput: ${lastInput} -- LastResponse: ${lastResponse}`)
}
helpers.ConLog(funcName, `ClickTraining for Train Dialog Row #${iRow} - ${firstInput}, ${lastInput}, ${lastResponse}`)
ClickTraining(iRow)
}).then(() => {
TdGrid.EditTrainingValidationPhase(TdGrid.iCurrentRow)
}).then(() => {
TdGrid.EditTrainingValidationPhase(TdGrid.iCurrentRow)
})
}
static EditTrainingByDescriptionAndOrTags(description, tagList, expectedRowCount = -1) {
const funcName = `EditTrainingByDescriptionAndOrTags(${description}, ${tagList})`
cy.Enqueue(() => {
TdGrid.GetAllRows(expectedRowCount)
}).then(() => {
let iRow = TdGrid.iCurrentRow = TdGrid.tdGrid.FindGridRowByDescriptionAndOrTags(description, tagList)
if (iRow < 0) {
if (iRow < 0) {
throw new Error(`Can't Find Training to Edit. The grid should, but does not, contain a row with this data in it: Description: '${description}' -- Tags: ${tagList}`)
}
helpers.ConLog(funcName, `ClickTraining for row: ${iRow}`)
ClickTraining(iRow)
}).then(() => {
TdGrid.EditTrainingValidationPhase(TdGrid.iCurrentRow)
}).then(() => {
TdGrid.EditTrainingValidationPhase(TdGrid.iCurrentRow)
})
}
@ -300,21 +300,21 @@ export class TdGrid {
helpers.ConLog(funcName, `Row #${iRow}`)
cy.wrap(1, {timeout: 8000}).should(() => {
cy.wrap(1, { timeout: 8000 }).should(() => {
const allChatMessageElements = chatPanel.GetAllChatMessageElements()
if (allChatMessageElements.length > 0) {
helpers.ConLog(funcName, `The expected Train Dialog from row #${iRow} has loaded`)
return
}
helpers.ConLog(funcName, `We are still waiting for the Train Dialog to load`)
retryCount++
if (retryCount % 5 == 0) {
helpers.ConLog(funcName, `Going to click on Train Dialog Row #${iRow} again.`)
// The problem with calling ClickTraining is that it causes the cy.wrap timeout to be canceled.
// CANNOT USE THIS - ClickTraining(iRow)
Cypress.$('[data-testid="train-dialogs-description"]')[iRow].click({force: true})
Cypress.$('[data-testid="train-dialogs-description"]')[iRow].click({ force: true })
throw new Error(`Retry - Clicked on Train Dialog Row #${iRow} again - need retry to verify TD loaded this time.`)
}
@ -323,11 +323,11 @@ export class TdGrid {
}
// Get all Train Dialog Grid Rows
static GetAllRows(expectedRowCount = -1) {
static GetAllRows(expectedRowCount = -1) {
const funcName = 'TdGrid.GetAllRows'
helpers.ConLog(funcName, 'start')
cy.WaitForStableDOM()
TdGrid.WaitForGridReadyThen(expectedRowCount, () => {
if (expectedRowCount >= 0 && TdGrid.tdGrid.rowCount != expectedRowCount) {
throw new Error(`The Train Dialog Grid does not have the ${expectedRowCount} expected rows, instead it has ${TdGrid.tdGrid.rowCount}`)
@ -338,7 +338,7 @@ export class TdGrid {
const lastResponses = TdGrid.tdGrid.lastResponses
const descriptions = TdGrid.tdGrid.descriptions
const tagLists = TdGrid.tdGrid.tagLists
let allRowData = []
for (let i = 0; i < firstInputs.length; i++) {
allRowData.push({
@ -348,10 +348,10 @@ export class TdGrid {
description: descriptions[i],
tagList: tagLists[i],
})
helpers.ConLog(funcName, `${allRowData[i].firstInput}, ${allRowData[i].lastInput}, ${allRowData[i].lastResponse}, ${allRowData[i].description}, ${allRowData[i].tagList}`)
}
TdGrid.currentData = allRowData
return allRowData
})
@ -377,11 +377,11 @@ export class TdGrid {
tagList: tagList,
}
if (TdGrid.iCurrentRow == TdGrid.currentData.length) {
TdGrid.currentData.push(newRowData)
if (TdGrid.iCurrentRow == TdGrid.currentData.length) {
TdGrid.currentData.push(newRowData)
}
else {
TdGrid.currentData[TdGrid.iCurrentRow] = newRowData
else {
TdGrid.currentData[TdGrid.iCurrentRow] = newRowData
}
}
@ -389,7 +389,7 @@ export class TdGrid {
VerifyListOfTrainDialogs(TdGrid.currentData)
}
// Private:
// Private:
// You should not be calling this directly unless you really know what you are doing.
constructor() {
this._firstInputs = undefined
@ -419,7 +419,7 @@ export class TdGrid {
setTimeout(TdGrid.MonitorGrid, 50)
return
}
if (new Date().getTime() < TdGrid.noMoreOverlaysExpectedTime) {
helpers.ConLog(funcName, 'No Overlay this time, but we are still watching to make sure no other overlay shows up for at least 1 second')
setTimeout(TdGrid.MonitorGrid, 50)
@ -429,7 +429,7 @@ export class TdGrid {
const elements = Cypress.$('[data-testid="train-dialogs-turns"]')
const rowCountsMessage = `Expected Row Count: ${TdGrid.expectedRowCount} - Actual Row Count: ${elements.length}`
if (TdGrid.expectedRowCount >= 0 && elements.length != TdGrid.expectedRowCount) {
if (TdGrid.expectedRowCount >= 0 && elements.length != TdGrid.expectedRowCount) {
helpers.ConLog(funcName, rowCountsMessage)
setTimeout(TdGrid.MonitorGrid, 50)
return
@ -451,15 +451,15 @@ TdGrid.iCurrentRow = -1 // Index of current row in grid that is being ed
TdGrid.tdGrid = undefined
export function VerifyIncidentTriangleFoundInTrainDialogsGrid(firstInput, lastInput, lastResponse, description = '', tagList = '', expectedRowCount = -1) {
FindGridRowByAllThenDo( firstInput, lastInput, lastResponse, description, tagList, expectedRowCount, VerifyErrorIconForTrainGridRow)
FindGridRowByAllThenDo(firstInput, lastInput, lastResponse, description, tagList, expectedRowCount, VerifyErrorIconForTrainGridRow)
}
export function VerifyNoIncidentTriangleFoundInTrainDialogsGrid(firstInput, lastInput, lastResponse, description = '', tagList = '', expectedRowCount = -1) {
FindGridRowByAllThenDo( firstInput, lastInput, lastResponse, description, tagList, expectedRowCount, VerifyNoErrorIconForTrainGridRow)
FindGridRowByAllThenDo(firstInput, lastInput, lastResponse, description, tagList, expectedRowCount, VerifyNoErrorIconForTrainGridRow)
}
export function ToggleRowSelection(firstInput, lastInput, lastResponse, description = '', tagList = '', expectedRowCount = -1) {
FindGridRowByAllThenDo( firstInput, lastInput, lastResponse, description, tagList, expectedRowCount, (iRow) => { cy.Get(`div.ms-List-cell[data-list-index="${iRow}"]`).find('div[role="checkbox"]').Click() })
FindGridRowByAllThenDo(firstInput, lastInput, lastResponse, description, tagList, expectedRowCount, (iRow) => { cy.Get(`div.ms-List-cell[data-list-index="${iRow}"]`).find('div[role="checkbox"]').Click() })
}
export function FindGridRowByAllThenDo(firstInput, lastInput, lastResponse, description = '', tagList = '', expectedRowCount = -1, func) {
@ -474,7 +474,7 @@ export function FindGridRowByAllThenDo(firstInput, lastInput, lastResponse, desc
throw new Error(`The Train Dialog Grid does not have the ${expectedRowCount} expected rows, instead it has ${TdGrid.tdGrid.rowCount}`)
}
if (iRow >= 0) {
if (iRow >= 0) {
func(iRow)
return
}
@ -487,21 +487,21 @@ export function VerifyListOfTrainDialogs(expectedTrainDialogs) {
helpers.ConLog(`VerifyListOfTrainDialogs(expectedRowCount: ${expectedRowCount})`, 'Start')
cy.log('Verify List of Train Dialogs', expectedRowCount)
TdGrid.WaitForGridReadyThen(expectedRowCount, tdGrid => {
TdGrid.WaitForGridReadyThen(expectedRowCount, tdGrid => {
let errors = false
expectedTrainDialogs.forEach(trainDialog => {
errors = errors || tdGrid.FindGridRowByAll(trainDialog.firstInput,
trainDialog.lastInput,
trainDialog.lastResponse,
trainDialog.description,
trainDialog.tagList) < 0
errors = errors || tdGrid.FindGridRowByAll(trainDialog.firstInput,
trainDialog.lastInput,
trainDialog.lastResponse,
trainDialog.description,
trainDialog.tagList) < 0
})
// We do this validation after we try to find the row so that more information about the potential failure is in the log.
if (expectedRowCount >= 0 && TdGrid.tdGrid.rowCount != expectedRowCount) {
throw new Error(`The Train Dialog Grid does not have the ${expectedRowCount} expected rows, instead it has ${TdGrid.tdGrid.rowCount}. Refer to the log file for more details.`)
}
if (errors) {
throw new Error('Did not find 1 or more of the expected Train Dialogs in the grid. Refer to the log file for details.')
}

Просмотреть файл

@ -1,7 +1,7 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as helpers from '../Helpers'

Просмотреть файл

@ -3,6 +3,21 @@ const ERROR_PANEL = 'ep'
const FULL_LOG = 'fl'
exports.triageData = [
{
searchBy: ERROR_PANEL,
and: [`LUIS Programmatic APIs v2.0 have exceeded rate limit of your current LUIS API`],
comment: 'Not much we can do about this except review our algorithm in .circleci\\SetLuisAuthoringKey.js to make sure there is enough keys to cycle through...or just pay for a LUIS license.',
},
{
searchBy: ERROR_PANEL,
and: [`Creating Application Failed Request failed with status code 400 "Bad Request {"Locale":["The Locale field is required."]}`],
bugs: [2408],
},
{
searchBy: ERROR_PANEL,
and: [`Running extractor Failed Request failed with status code 502 "Bad Gateway "LUIS error:`],
comment: 'Network Issues - It should eventually fix itself.',
},
{
or: [
`Timed out retrying: Stauts is queued - Still Waiting for Status == Running or Completed - Queued Wait Time:`,
@ -72,16 +87,6 @@ exports.triageData = [
],
comment: 'This happens from time to time and there is no known fix for it.',
},
{
searchBy: ERROR_PANEL,
and: [`Creating Application Failed Request failed with status code 400 "Bad Request {"Locale":["The Locale field is required."]}`],
bugs: [2408],
},
{
searchBy: ERROR_PANEL,
and: [`Running extractor Failed Request failed with status code 502 "Bad Gateway "LUIS error:`],
comment: 'Network Issues - It should eventually fix itself.',
},
{
searchBy: FULL_LOG,
and: [