@qualtrics/plugin-ui-react 1.3.3 → 1.4.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.dockerignore +10 -0
  2. package/.eslintrc.js +1 -1
  3. package/Dockerfile +18 -0
  4. package/Makefile +33 -4
  5. package/README.md +28 -0
  6. package/dist/common/capture-event/capture-event.d.ts +13 -0
  7. package/dist/common/capture-event/capture-event.test.d.ts +1 -0
  8. package/dist/common/copy-text/copy-text.d.ts +8 -0
  9. package/dist/common/copy-text/copy-text.test.d.ts +1 -0
  10. package/dist/common/field-mapper/field-mapper-key/field-mapper-key.d.ts +12 -0
  11. package/dist/common/field-mapper/field-mapper-row/field-mapper-row.d.ts +17 -0
  12. package/dist/common/field-mapper/field-mapper-value/field-mapper-value.d.ts +11 -0
  13. package/dist/common/field-mapper/field-mapper.d.ts +20 -0
  14. package/dist/common/field-mapper/index.d.ts +4 -0
  15. package/dist/common/piped-text-input/piped-text-input.d.ts +2 -2
  16. package/dist/common/piped-text-select/piped-text-menu/piped-text-menu-item/piped-text-menu-item.d.ts +16 -0
  17. package/dist/common/piped-text-select/piped-text-menu/piped-text-submenu-item/piped-text-submenu-item.d.ts +13 -0
  18. package/dist/common/portal.d.ts +3 -0
  19. package/dist/hooks/use-id.d.ts +7 -0
  20. package/dist/index.d.ts +4 -1
  21. package/dist/lib/models/field-mapper-item.d.ts +7 -0
  22. package/dist/lib/models/piped-text-menu-item-data.d.ts +21 -0
  23. package/dist/lib/models/piped-text.d.ts +16 -0
  24. package/dist/lib/type-validation/validate-primitives.d.ts +1 -0
  25. package/dist/main.es.js +959 -172
  26. package/dist/main.js +963 -170
  27. package/jenkins.groovy +284 -0
  28. package/jenkinsPipelineUtils/jira.groovy +84 -0
  29. package/jenkinsPipelineUtils/notifications.groovy +34 -0
  30. package/jenkinsPipelineUtils/pipelineControls.groovy +56 -0
  31. package/jenkinsPipelineUtils/trs.groovy +30 -0
  32. package/package.json +7 -6
  33. package/test_results/junit.xml +101 -0
  34. package/.bee +0 -2
  35. package/Jenkinsfile +0 -109
  36. package/bee +0 -932
package/jenkins.groovy ADDED
@@ -0,0 +1,284 @@
1
+ // Job Parameters
2
+ JOB_PARAMETER_RELEASE_STEP_PUBLISH = 'publish'
3
+ JOB_PARAMETER_RELEASE_STEP_PC_TICKETS = 'pc tickets'
4
+
5
+ JOB_PARAMETER_PROJECT_PLUGIN_UI_REACT = 'plugin-ui-react'
6
+
7
+ PUBLIC_REGISTRY = 'https://registry.npmjs.org'
8
+
9
+ // Project Contstants
10
+ SLACK_DEPLOY_CHANNEL = '#app-sdk-deploys'
11
+ SLACK_MR_VALIDATION_CHANNEL = '#app-sdk-mr-validation'
12
+
13
+ PROJECTS = [
14
+ [
15
+ name: '@qualtrics/plugin-ui-react',
16
+ directory: '.',
17
+ jobParameterProject: JOB_PARAMETER_PROJECT_PLUGIN_UI_REACT,
18
+ trsId: '1d15e1dc-f156-45a2-966e-89dba1797e68',
19
+ trsServiceTag: 'qualtrics-plugin-ui-react'
20
+ ]
21
+ ]
22
+
23
+ TRS_TEAM = 'appsdk'
24
+ TRS_GRAFANA_PROJECT_URL = "https://grafana.eng.qops.net/d/2qriuzfMk/trs-unit-tests-by-service?orgId=1&refresh=1h&var-unit_team=${TRS_TEAM}"
25
+ TEST_RESULTS_FILE = 'junit.xml'
26
+ CODE_COVERAGE_FILE = 'cobertura-coverage.xml'
27
+
28
+ JIRA_SERVICE_TEAM_ID = '18254'
29
+ JIRA_LABELS = ['DPEE']
30
+ TEAM_RUNBOOK = 'https://odo.corp.qualtrics.com/wiki/index.php/AppSDK_Team_Runbook'
31
+ TEAM_ROLLBACK = 'https://odo.corp.qualtrics.com/wiki/index.php/AppSDK_Team_Runbook#Task_Rollback'
32
+
33
+ MAKE_PUBLISH_EXTERNAL = 'make publish-external'
34
+ MAKE_BUILD = 'make build'
35
+ MAKE_TEST = 'make test'
36
+ MAKE_CLEAN = 'make clean'
37
+
38
+ MAIN_BRANCH = 'master'
39
+
40
+ pipeline {
41
+ agent {
42
+ label 'nomad-builder'
43
+ }
44
+ environment {
45
+ DOCKER_HOST = '127.0.0.1:2375'
46
+ WORKSPACE_PATH = "/var/lib/nomad/alloc/${NOMAD_ALLOC_ID}/${NOMAD_TASK_NAME}${WORKSPACE}"
47
+ }
48
+
49
+ options {
50
+ timestamps()
51
+ buildDiscarder(logRotator(numToKeepStr: '5'))
52
+ timeout(time: 60, unit: 'MINUTES')
53
+ }
54
+
55
+ stages {
56
+ stage('Setup') {
57
+ steps {
58
+ script {
59
+ def rootDir = pwd()
60
+ def jenkinsUtilsFolder = "${rootDir}/jenkinsPipelineUtils"
61
+ trs = load("${jenkinsUtilsFolder}/trs.groovy")
62
+ jira = load("${jenkinsUtilsFolder}/jira.groovy")
63
+ notifications = load("${jenkinsUtilsFolder}/notifications.groovy")
64
+ pipelineControls = load("${jenkinsUtilsFolder}/pipelineControls.groovy")
65
+
66
+ notifications.setCommitStatus('running')
67
+
68
+ PROJECT_NAME_VERSION = ''
69
+
70
+ for (project in PROJECTS) {
71
+ def nameVersion = getProjectNameAndVersion(project.name, project.directory)
72
+ PROJECT_NAME_VERSION += "${nameVersion} "
73
+ TRS_GRAFANA_PROJECT_URL += "&var-unit_service=${project.trsServiceTag}"
74
+ echo "Project: ${nameVersion}"
75
+ }
76
+ echo "Workspace: ${WORKSPACE_PATH}"
77
+ echo "Git action: ${env.gitlabActionType}"
78
+ echo "Git source branch: ${env.gitlabSourceBranch}"
79
+
80
+ currentBuild.displayName = pipelineControls.getJobDisplayName(currentBuild.number, PROJECT_NAME_VERSION, MAIN_BRANCH)
81
+ }
82
+ }
83
+ }
84
+ stage('Build') {
85
+ when {
86
+ expression {
87
+ !isManualPCTicketJob()
88
+ }
89
+ }
90
+ steps {
91
+ sh script: MAKE_BUILD
92
+ }
93
+ }
94
+ stage('Unit Test') {
95
+ when {
96
+ expression {
97
+ !isManualPCTicketJob()
98
+ }
99
+ }
100
+ steps {
101
+ script {
102
+ for (project in PROJECTS) {
103
+ echo "testing ${project.name}"
104
+ sh script: "${MAKE_TEST} DIRECTORY=${project.directory}"
105
+ }
106
+ }
107
+ }
108
+ }
109
+ stage('TRS') {
110
+ when {
111
+ expression {
112
+ pipelineControls.isPushToMain(MAIN_BRANCH)
113
+ }
114
+ }
115
+ steps {
116
+ script {
117
+ for (project in PROJECTS) {
118
+ publishToTRS(project)
119
+ }
120
+ echo "To see the TRS dashboard vist ${TRS_GRAFANA_PROJECT_URL}"
121
+ }
122
+ }
123
+ }
124
+ stage('PC Tickets') {
125
+ when {
126
+ expression {
127
+ isManualPCTicketJob()
128
+ }
129
+ }
130
+ steps {
131
+ script {
132
+ for (project in PROJECTS) {
133
+ if (project.jobParameterProject == JOB_PARAMETER_PROJECT) {
134
+ createPCReleaseTicket(project)
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ stage('Publish') {
141
+ when {
142
+ expression {
143
+ pipelineControls.isPushToMain(MAIN_BRANCH) || JOB_PARAMETER_RELEASE_STEP == JOB_PARAMETER_RELEASE_STEP_PUBLISH
144
+ }
145
+ }
146
+ steps {
147
+ script {
148
+ for (project in PROJECTS) {
149
+ if (isDeploymentJob(project.jobParameterProject, project.directory)) {
150
+ publishToNpm(project)
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ post {
159
+ success {
160
+ script {
161
+ if (!isManualPCTicketJob()) {
162
+ def validationChannel = pipelineControls.isMergeRequest(MAIN_BRANCH) ? SLACK_MR_VALIDATION_CHANNEL : SLACK_DEPLOY_CHANNEL
163
+ notifications.sendSlackVerifiedProjectMessage(PROJECT_NAME_VERSION, validationChannel)
164
+ }
165
+ notifications.setCommitStatus('success')
166
+ }
167
+ }
168
+ failure {
169
+ script {
170
+ def validationChannel = pipelineControls.isMergeRequest(MAIN_BRANCH) ? SLACK_MR_VALIDATION_CHANNEL : SLACK_DEPLOY_CHANNEL
171
+ notifications.sendSlackFailedToVerifyProjectMessage(PROJECT_NAME_VERSION, validationChannel)
172
+ notifications.setCommitStatus('failed')
173
+ }
174
+ }
175
+ aborted {
176
+ script {
177
+ notifications.setCommitStatus('canceled')
178
+ }
179
+ }
180
+ always {
181
+ sh script: MAKE_CLEAN
182
+ }
183
+ }
184
+ }
185
+
186
+ def publishToTRS(project) {
187
+ echo "publishing ${project.name} to TRS"
188
+ def resultsDir = "./coverage/${project.directory}/${TEST_RESULTS_FILE}"
189
+ def coverageDir = "./coverage/${project.directory}/${CODE_COVERAGE_FILE}"
190
+ trs.publishResultsToTRS(project.trsId, project.trsServiceTag, resultsDir, coverageDir, WORKSPACE_PATH, TRS_TEAM)
191
+ }
192
+
193
+ def createPCReleaseTicket(project) {
194
+ def nameVersion = getProjectNameAndVersion(project.name, project.directory)
195
+ echo "creating PC ticket for ${nameVersion}"
196
+
197
+ def pcTicketUrl = jira.createPCTicket(nameVersion, JIRA_SERVICE_TEAM_ID, TEAM_RUNBOOK, TEAM_ROLLBACK, JIRA_LABELS)
198
+ notifications.sendPCTicketCreatedMessage(pcTicketUrl, nameVersion, SLACK_DEPLOY_CHANNEL)
199
+
200
+ echo "PC ticket for ${nameVersion} was created"
201
+ echo "PC ticket URL: ${pcTicketUrl}"
202
+ }
203
+
204
+ def publishToNpm(project) {
205
+ def nameVersion = getProjectNameAndVersion(project.name, project.directory)
206
+ echo "publishing ${nameVersion}"
207
+
208
+ if (hasVersionBeenPublished(project)) {
209
+ def alreadyPublishedMessage = "${nameVersion} has already been published."
210
+ if (isManualDeployJob()) {
211
+ notifications.sendSlackFailedToPublishMessage(nameVersion, SLACK_DEPLOY_CHANNEL)
212
+ erorr alreadyPublishedMessage
213
+ }
214
+ echo "${alreadyPublishedMessage} Skipping..."
215
+ return
216
+ }
217
+
218
+ def packageJsonPath = getPackageJsonPath(project.directory)
219
+ def tag = pipelineControls.isAlphaVersion(packageJsonPath) ? 'alpha' : 'latest'
220
+ def publishStatus = publishToPublicRegistry(project.directory, tag)
221
+
222
+ if (publishStatus == 0) {
223
+ echo "${nameVersion} was published"
224
+ notifications.sendSlackPublishedMessage(nameVersion, SLACK_DEPLOY_CHANNEL)
225
+ } else {
226
+ notifications.sendSlackFailedToPublishMessage(nameVersion, SLACK_DEPLOY_CHANNEL)
227
+
228
+ def failureMessage = "Unable to publish ${nameVersion}"
229
+ echo failureMessage
230
+ if (isManualDeployJob()) {
231
+ throw new Error(failureMessage)
232
+ }
233
+ }
234
+ }
235
+
236
+ def publishToPublicRegistry(directory, tag) {
237
+ def publishStatus = 0
238
+ def configuration = [vaultCredentialId: 'INT_NPM_PUBLISH_TOKEN']
239
+ def secrets = [
240
+ [path: 'secret/dev-platform/teams/appsdk/npm-public-registry', secretValues: [
241
+ [envVar: 'INT_NPM_TOKEN', vaultKey: 'int_npm_publish_token'],
242
+ ]],
243
+ ]
244
+ withVault([configuration: configuration, vaultSecrets: secrets]) {
245
+ publishStatus = sh(returnStatus: true, script: 'INT_NPM_TOKEN=$INT_NPM_TOKEN ' + "DIRECTORY=${directory} TAG=${tag} ${MAKE_PUBLISH_EXTERNAL}")
246
+ }
247
+ return publishStatus
248
+ }
249
+
250
+ def isManualPCTicketJob() {
251
+ return pipelineControls.isManual() && JOB_PARAMETER_RELEASE_STEP == JOB_PARAMETER_RELEASE_STEP_PC_TICKETS
252
+ }
253
+
254
+ def isManualDeployJob() {
255
+ return pipelineControls.isManual() && JOB_PARAMETER_RELEASE_STEP == JOB_PARAMETER_RELEASE_STEP_PUBLISH
256
+ }
257
+
258
+ def isDeploymentJob(jobParameterProject, directory) {
259
+ def packageJsonPath = getPackageJsonPath(directory)
260
+ if (isManualDeployJob()) {
261
+ return JOB_PARAMETER_PROJECT == jobParameterProject
262
+ }
263
+ return pipelineControls.isAlphaRelease(packageJsonPath, MAIN_BRANCH)
264
+ }
265
+
266
+ def getPackageJsonPath(directory) {
267
+ def rootDir = pwd()
268
+ return "${rootDir}/${directory}/package.json"
269
+ }
270
+
271
+ def getProjectNameAndVersion(name, directory) {
272
+ def version = getPackageVersion(directory)
273
+ return "${name}@${version}"
274
+ }
275
+
276
+ def getPackageVersion(directory) {
277
+ def packageJsonPath = getPackageJsonPath(directory)
278
+ return pipelineControls.parseVersionNumber(packageJsonPath)
279
+ }
280
+
281
+ def hasVersionBeenPublished(project) {
282
+ def version = getPackageVersion(project.directory)
283
+ return pipelineControls.hasPackageBeenPreviouslyPublished(project.name, version, PUBLIC_REGISTRY)
284
+ }
@@ -0,0 +1,84 @@
1
+ import groovy.json.JsonOutput
2
+ import groovy.json.JsonSlurper
3
+
4
+ // JIRA ID's
5
+ CHANGE_TYPE_FIELD_ID = 'customfield_17900'
6
+ SERVICE_TEAM_FIELD_ID = 'customfield_12900'
7
+ RISK_FIELD_ID = 'customfield_14500'
8
+ IMPACT_FIELD_ID = 'customfield_15200'
9
+ DILIGENCE_FIELD_ID = 'customfield_15201'
10
+ DATA_CENTER_FIELD_ID = 'customfield_10400'
11
+ RUNBOOK_FIELD_ID = 'customfield_15202'
12
+ ROLLBACK_PLAN_FIELD_ID = 'customfield_15203'
13
+ PROD_CHANGE_CHECKLIST_FIELD_ID = 'customfield_11503'
14
+
15
+ STANDARD_DEPLOYMENT_ID = '16503'
16
+ LOW_RISK_ID = '13602'
17
+ LOW_IMPACT_ID = '14302'
18
+ LOW_DILIGENCE_ID = '14305'
19
+ STATIC_ASSETS_ID = '18113'
20
+
21
+
22
+ def createPCTicket(nameVersion, serviceTeamId, runBookUrl, rollbackUrl, labels) {
23
+ data = [
24
+ fields: [
25
+ labels: labels,
26
+ project: [key: 'PC'],
27
+ issuetype: [id: '10000'],
28
+ summary: "Publish ${nameVersion} to production",
29
+ description: "Publishing ${nameVersion} to production",
30
+ (SERVICE_TEAM_FIELD_ID): [id: serviceTeamId],
31
+ (RUNBOOK_FIELD_ID): runBookUrl,
32
+ (ROLLBACK_PLAN_FIELD_ID): rollbackUrl,
33
+ (CHANGE_TYPE_FIELD_ID): [id: STANDARD_DEPLOYMENT_ID],
34
+ (RISK_FIELD_ID): [id: LOW_RISK_ID],
35
+ (IMPACT_FIELD_ID): [id: LOW_IMPACT_ID],
36
+ (DILIGENCE_FIELD_ID): [id: LOW_DILIGENCE_ID],
37
+ (DATA_CENTER_FIELD_ID): [[id: STATIC_ASSETS_ID]],
38
+ (PROD_CHANGE_CHECKLIST_FIELD_ID): """
39
+ What: ${nameVersion}
40
+ When: Now
41
+ Why: New version
42
+ Risk: low
43
+ Customer Impact: low
44
+ Code Reviewer: appsdk
45
+ Who will be reviewing the change as it is conducted? <FILL OUT>
46
+ What have you done to test this change? manually tested the corresponding alpha release
47
+ What will you do to validate this change? manually test the newly released version
48
+ """
49
+ ]
50
+ ]
51
+ issueId = callJira(data)
52
+ issueUrl = "https://qualtrics.atlassian.net/browse/${issueId}"
53
+ return issueUrl
54
+ }
55
+
56
+ def callJira(data) {
57
+ def body = JsonOutput.toJson(data)
58
+ def escapedBody = body.replaceAll("'", "'\"'\"'")
59
+ def configuration = [$class: 'VaultConfiguration', vaultCredentialId: 'INTEGRATIONS-EXTENSION-JENKINS_VAULT-TOKEN']
60
+ def secrets = [[$class: 'VaultSecret', path: 'secret/external-apis/jira/it-jira-admin/prod', secretValues: [
61
+ [envVar: 'JIRA_API_TOKEN', vaultKey: 'JIRA_API_TOKEN'],
62
+ [envVar: 'JIRA_API_EMAIL_ADDRESS', vaultKey: 'JIRA_API_EMAIL_ADDRESS']
63
+ ]]]
64
+ wrap([$class: 'VaultBuildWrapper', configuration: configuration, vaultSecrets: secrets]) {
65
+ response = sh(
66
+ script: """
67
+ curl -s -X 'POST' \
68
+ -H 'Content-Type: application/json' \
69
+ -u '${JIRA_API_EMAIL_ADDRESS}:${JIRA_API_TOKEN}' \
70
+ -d '${escapedBody}' \
71
+ 'https://qualtrics.atlassian.net/rest/api/2/issue'
72
+ """,
73
+ returnStdout: true
74
+ ).trim()
75
+ }
76
+ if (response == '') {
77
+ return []
78
+ }
79
+ echo response
80
+ def parsedResponse = new JsonSlurper().parseText(response)
81
+ return parsedResponse.key
82
+ }
83
+
84
+ return this
@@ -0,0 +1,34 @@
1
+ def sendSlackPublishedMessage(projectName, channel) {
2
+ def message = ":rocket: <${BUILD_URL}| Published> *${projectName}*"
3
+ slackSend color: 'good', message: message, channel: channel
4
+ }
5
+
6
+ def sendSlackFailedToPublishMessage(projectName, channel) {
7
+ def message = ":boom: Failed to <${BUILD_URL}| publish> *${projectName}*"
8
+ slackSend color: 'warning', message: message, channel: channel
9
+ }
10
+
11
+ def sendSlackVerifiedProjectMessage(projectName, channel) {
12
+ def message = ":four_leaf_clover: *${projectName}* <${BUILD_URL}| passed> validation"
13
+ slackSend color: 'good', message: message, channel: channel
14
+ }
15
+
16
+ def sendSlackFailedToVerifyProjectMessage(projectName, channel) {
17
+ def message = ":hot_pepper: *${projectName}* <${BUILD_URL}| failed> validation"
18
+ slackSend color: 'warning', message: message, channel: channel
19
+ }
20
+
21
+ def sendPCTicketCreatedMessage(pcTicketUrl, projectName, channel) {
22
+ def message = ":mailbox: <${pcTicketUrl}| PC ticket> for ${projectName} created"
23
+ slackSend color: 'good', message: message, channel: channel
24
+ }
25
+
26
+ def setCommitStatus(status) {
27
+ try {
28
+ updateGitlabCommitStatus name: JOB_NAME, state: status
29
+ } catch (Exception ex) {
30
+ echo "Ignoring Gitlab commit status error ${ex}"
31
+ }
32
+ }
33
+
34
+ return this
@@ -0,0 +1,56 @@
1
+ import groovy.json.JsonSlurper
2
+
3
+ PUSH = 'PUSH'
4
+ NOTE = 'NOTE'
5
+
6
+ def getJobDisplayName(currentBuildNumber, projectName, mainBranch) {
7
+ if (isMergeRequest(mainBranch)) {
8
+ def commitHash = sh(returnStdout: true, script: 'git rev-parse --short HEAD | tr -d \'[:space:]\'')
9
+ return "#${currentBuildNumber} - MR Validation ${commitHash}"
10
+ } else {
11
+ return "#${currentBuild.number} - Publishing ${projectName}"
12
+ }
13
+ }
14
+
15
+ def parseVersionNumber(packageJsonPath) {
16
+ def versionNumberPattern = /(\d+).(\d+).(\d+(-alpha.(\d)+)?)/
17
+ def manifest = readFile(packageJsonPath)
18
+ def version = (manifest =~ /\"version\": \"${versionNumberPattern}\"/)
19
+ version = (version[0][0] =~ /${versionNumberPattern}/)
20
+ return version[0][0]
21
+ }
22
+
23
+ def isAlphaVersion(packageJsonPath) {
24
+ def folderVerionNumber = parseVersionNumber(packageJsonPath)
25
+ return folderVerionNumber.contains('-alpha')
26
+ }
27
+
28
+ def isMergeRequest(mainBranch) {
29
+ return (env.gitlabActionType == PUSH || env.gitlabActionType == NOTE) && env.gitlabSourceBranch != mainBranch
30
+ }
31
+
32
+ def isPushToMain(mainBranch) {
33
+ return env.gitlabActionType == PUSH && env.gitlabSourceBranch == mainBranch
34
+ }
35
+
36
+ def isManual() {
37
+ return env.gitlabSourceBranch == null
38
+ }
39
+
40
+ def isAlphaRelease(packageJsonPath, mainBranch) {
41
+ return isPushToMain(MAIN_BRANCH) && isAlphaVersion(packageJsonPath)
42
+ }
43
+
44
+ def hasPackageBeenPreviouslyPublished(packageName, packageVersion, registryUrl) {
45
+ try {
46
+ def getPackageVersionScript = "curl ${registryUrl}/${packageName}/${packageVersion}"
47
+ def packageVersionString = sh(script: getPackageVersionScript, returnStdout: true)
48
+ def parsedPackageVersion = new JsonSlurper().parseText(packageVersionString)
49
+ return parsedPackageVersion instanceof Map && parsedPackageVersion.containsKey("name")
50
+ } catch(Exception e) {
51
+ echo e
52
+ error "Was unable to check if package version has been already published"
53
+ }
54
+ }
55
+
56
+ return this
@@ -0,0 +1,30 @@
1
+ def publishResultsToTRS(uuid, serviceTag, reportFilePath, coverageFilePath, workspacePath, team) {
2
+ if (!fileExists(reportFilePath)) {
3
+ currentBuild.result = 'FAILURE'
4
+ echo 'Was not able to find test result artifacts'
5
+ return
6
+ }
7
+
8
+ if (!fileExists(coverageFilePath)) {
9
+ currentBuild.result = 'FAILURE'
10
+ echo 'Was not able to find code coverage artifacts'
11
+ return
12
+ }
13
+
14
+ sh """
15
+ docker run --rm \
16
+ -e REPORT_CONFIG_ID=${uuid} \
17
+ -e TEAM_NAME_TAG="${team}" \
18
+ -e SERVICE_NAME_TAG="${serviceTag}" \
19
+ -e TEST_TYPE_TAG="unittests" \
20
+ -e REPORT_FILE_PATH=\"./mounted/${reportFilePath}\" \
21
+ -e REPORT_TYPE=JUNIT \
22
+ -v \"${workspacePath}/${reportFilePath}\":/home/node/mounted/${reportFilePath} \
23
+ -e CODE_COVERAGE_FILE_PATH=\"./mounted/${coverageFilePath}\" \
24
+ -e CODE_COVERAGE_REPORT_TYPE=COBERTURA \
25
+ -v \"${workspacePath}/${coverageFilePath}\":/home/node/mounted/${coverageFilePath} \
26
+ registry-app.eng.qops.net:5001/test-tools/trs-uploader
27
+ """
28
+ }
29
+
30
+ return this
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qualtrics/plugin-ui-react",
3
- "version": "1.3.3",
3
+ "version": "1.4.0-alpha.0",
4
4
  "description": "",
5
5
  "main": "dist/main.js",
6
6
  "module": "dist/main.es.js",
@@ -12,9 +12,10 @@
12
12
  "purge": "echo 'hi'",
13
13
  "deps": "npm i --no-save @qualtrics/ui-react @qualtrics/base-styles react react-dom",
14
14
  "deps:react": "npm i --no-save react react-dom",
15
- "trs-deps": "yarn add @qualtrics/ui-react @qualtrics/base-styles react react-dom",
15
+ "trs-deps": "npm add @qualtrics/ui-react @qualtrics/base-styles react react-dom",
16
16
  "test": "npm run deps && jest --silent",
17
- "test:trs": "yarn install --ignore-engines; yarn add @qualtrics/ui-react @qualtrics/base-styles --ignore-engines && jest --silent"
17
+ "test:trs": "npm run test",
18
+ "prerelease-alpha": "npm version prerelease --preid=alpha"
18
19
  },
19
20
  "publishConfig": {
20
21
  "registry": "https://registry.npmjs.org/"
@@ -41,10 +42,10 @@
41
42
  "@types/lodash.get": "^4.4.6",
42
43
  "@types/react": "^17.0.11",
43
44
  "@types/react-dom": "^17.0.8",
45
+ "@types/uuid": "^8.3.3",
44
46
  "@typescript-eslint/eslint-plugin": "^4.28.0",
45
47
  "@typescript-eslint/parser": "^4.28.0",
46
48
  "eslint": "^7.29.0",
47
- "eslint-config-qualtrics-react-js": "^1.0.0",
48
49
  "eslint-plugin-jest": "^24.3.6",
49
50
  "eslint-plugin-json-format": "^2.0.1",
50
51
  "eslint-plugin-react": "^7.24.0",
@@ -76,7 +77,7 @@
76
77
  },
77
78
  "peerDependencies": {
78
79
  "@qualtrics/base-styles": "^0.2.1",
79
- "@qualtrics/ui-react": "^1.60.0",
80
+ "@qualtrics/ui-react": "^1.95.0",
80
81
  "react": "^16.8.0",
81
82
  "react-dom": "^16.8.0"
82
83
  },
@@ -108,7 +109,7 @@
108
109
  [
109
110
  "jest-junit",
110
111
  {
111
- "outputDirectory": "test_results"
112
+ "outputDirectory": "coverage"
112
113
  }
113
114
  ]
114
115
  ],
@@ -0,0 +1,101 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <testsuites name="jest tests" tests="41" failures="0" errors="0" time="17.093">
3
+ <testsuite name="FieldItem" errors="0" failures="0" skipped="0" timestamp="2021-11-15T23:34:01" time="2.989" tests="2">
4
+ <testcase classname="FieldItem renders properly" name="FieldItem renders properly" time="0.019">
5
+ </testcase>
6
+ <testcase classname="FieldItem invokes onClick handler with expected arguments when clicked" name="FieldItem invokes onClick handler with expected arguments when clicked" time="0.048">
7
+ </testcase>
8
+ </testsuite>
9
+ <testsuite name="SelectItem" errors="0" failures="0" skipped="0" timestamp="2021-11-15T23:34:01" time="3.927" tests="1">
10
+ <testcase classname="SelectItem fires the onChange handler with expected args" name="SelectItem fires the onChange handler with expected args" time="0.051">
11
+ </testcase>
12
+ </testsuite>
13
+ <testsuite name="DynamicSearchInput" errors="0" failures="0" skipped="0" timestamp="2021-11-15T23:34:01" time="4.657" tests="1">
14
+ <testcase classname="DynamicSearchInput renders correctly" name="DynamicSearchInput renders correctly" time="0.001">
15
+ </testcase>
16
+ </testsuite>
17
+ <testsuite name="MultiselectDropdown" errors="0" failures="0" skipped="0" timestamp="2021-11-15T23:34:01" time="5.095" tests="3">
18
+ <testcase classname="MultiselectDropdown toggles dropdown when button is clicked" name="MultiselectDropdown toggles dropdown when button is clicked" time="0.228">
19
+ </testcase>
20
+ <testcase classname="MultiselectDropdown calls onChange handler when item is clicked" name="MultiselectDropdown calls onChange handler when item is clicked" time="0.186">
21
+ </testcase>
22
+ <testcase classname="MultiselectDropdown closes menu on click away" name="MultiselectDropdown closes menu on click away" time="0.051">
23
+ </testcase>
24
+ </testsuite>
25
+ <testsuite name="FieldRow" errors="0" failures="0" skipped="0" timestamp="2021-11-15T23:34:01" time="5.164" tests="6">
26
+ <testcase classname="FieldRow fires the onFieldNameChange handler when field name is changed" name="FieldRow fires the onFieldNameChange handler when field name is changed" time="0.062">
27
+ </testcase>
28
+ <testcase classname="FieldRow fires the onFieldValueChange handler when field&apos;s value is changed" name="FieldRow fires the onFieldValueChange handler when field&apos;s value is changed" time="0.031">
29
+ </testcase>
30
+ <testcase classname="FieldRow fires the onFieldSwitch handler when field is switched to different field type" name="FieldRow fires the onFieldSwitch handler when field is switched to different field type" time="0.054">
31
+ </testcase>
32
+ <testcase classname="FieldRow fires the onRemove handler when the delete button is clicked" name="FieldRow fires the onRemove handler when the delete button is clicked" time="0.026">
33
+ </testcase>
34
+ <testcase classname="FieldRow should allow for searching in field row input dropdown when searchable field provided" name="FieldRow should allow for searching in field row input dropdown when searchable field provided" time="0.205">
35
+ </testcase>
36
+ <testcase classname="FieldRow should not allow searching in field row input dropdown when searchable is false" name="FieldRow should not allow searching in field row input dropdown when searchable is false" time="0.022">
37
+ </testcase>
38
+ </testsuite>
39
+ <testsuite name="TaskFields" errors="0" failures="0" skipped="0" timestamp="2021-11-15T23:34:01" time="5.336" tests="4">
40
+ <testcase classname="TaskFields only renders custom fields if custom field configuration options provided" name="TaskFields only renders custom fields if custom field configuration options provided" time="0.441">
41
+ </testcase>
42
+ <testcase classname="TaskFields fires onFieldNameChange handler when a custom field&apos;s name is changed" name="TaskFields fires onFieldNameChange handler when a custom field&apos;s name is changed" time="0.034">
43
+ </testcase>
44
+ <testcase classname="TaskFields fires onFieldAdd handler when a field is added" name="TaskFields fires onFieldAdd handler when a field is added" time="0.056">
45
+ </testcase>
46
+ <testcase classname="TaskFields fires onCustomFieldAdd handler when a custom field is added" name="TaskFields fires onCustomFieldAdd handler when a custom field is added" time="0.047">
47
+ </testcase>
48
+ </testsuite>
49
+ <testsuite name="PipedTextInput" errors="0" failures="0" skipped="0" timestamp="2021-11-15T23:34:01" time="5.506" tests="6">
50
+ <testcase classname="PipedTextInput toggles menu open/closed on click" name="PipedTextInput toggles menu open/closed on click" time="0.352">
51
+ </testcase>
52
+ <testcase classname="PipedTextInput fires onChange handler when input value changes from selecting piped text" name="PipedTextInput fires onChange handler when input value changes from selecting piped text" time="0.117">
53
+ </testcase>
54
+ <testcase classname="PipedTextInput fires onChange handler when input value changes from user typing in input box" name="PipedTextInput fires onChange handler when input value changes from user typing in input box" time="0.01">
55
+ </testcase>
56
+ <testcase classname="PipedTextInput fires onSelect handler when piped text is selected" name="PipedTextInput fires onSelect handler when piped text is selected" time="0.097">
57
+ </testcase>
58
+ <testcase classname="PipedTextInput fires onClose handler when menu is closed" name="PipedTextInput fires onClose handler when menu is closed" time="0.086">
59
+ </testcase>
60
+ <testcase classname="PipedTextInput inserts piped text at the position of the cursor in the input box when piped text is selected" name="PipedTextInput inserts piped text at the position of the cursor in the input box when piped text is selected" time="0.086">
61
+ </testcase>
62
+ </testsuite>
63
+ <testsuite name="PipedTextSelect" errors="0" failures="0" skipped="0" timestamp="2021-11-15T23:34:01" time="13.594" tests="18">
64
+ <testcase classname="PipedTextSelect filters menu items to items containing the search value as text" name="PipedTextSelect filters menu items to items containing the search value as text" time="0.383">
65
+ </testcase>
66
+ <testcase classname="PipedTextSelect filters menu items to items containing the search value as a substring" name="PipedTextSelect filters menu items to items containing the search value as a substring" time="0.17">
67
+ </testcase>
68
+ <testcase classname="PipedTextSelect filters menu items with special characters to items containing the search value" name="PipedTextSelect filters menu items with special characters to items containing the search value" time="0.169">
69
+ </testcase>
70
+ <testcase classname="PipedTextSelect renders submenu correctly when hovering over a submenu item" name="PipedTextSelect renders submenu correctly when hovering over a submenu item" time="0.627">
71
+ </testcase>
72
+ <testcase classname="PipedTextSelect hides other submenus when hovering over another submenu" name="PipedTextSelect hides other submenus when hovering over another submenu" time="0.714">
73
+ </testcase>
74
+ <testcase classname="PipedTextSelect hides other submenus when hovering over another item" name="PipedTextSelect hides other submenus when hovering over another item" time="0.283">
75
+ </testcase>
76
+ <testcase classname="PipedTextSelect fires onSelect handler when a menu item is selected" name="PipedTextSelect fires onSelect handler when a menu item is selected" time="0.219">
77
+ </testcase>
78
+ <testcase classname="PipedTextSelect doesn&apos;t fire onSelect handler when a disabled menu item is selected" name="PipedTextSelect doesn&apos;t fire onSelect handler when a disabled menu item is selected" time="0.174">
79
+ </testcase>
80
+ <testcase classname="PipedTextSelect fires onClose handler when menu item selected" name="PipedTextSelect fires onClose handler when menu item selected" time="0.151">
81
+ </testcase>
82
+ <testcase classname="PipedTextSelect fires onClose handler when nested item selected" name="PipedTextSelect fires onClose handler when nested item selected" time="1.345">
83
+ </testcase>
84
+ <testcase classname="PipedTextSelect fires onClose handler when clicking outside of the menu" name="PipedTextSelect fires onClose handler when clicking outside of the menu" time="0.044">
85
+ </testcase>
86
+ <testcase classname="PipedTextSelect displays the custom input message if none of the menu items match the search query and custom input is enabled" name="PipedTextSelect displays the custom input message if none of the menu items match the search query and custom input is enabled" time="0.578">
87
+ </testcase>
88
+ <testcase classname="PipedTextSelect correctly creates a custom locator based on the provided scheme when the user hits the &quot;enter&quot; in the search query" name="PipedTextSelect correctly creates a custom locator based on the provided scheme when the user hits the &quot;enter&quot; in the search query" time="0.558">
89
+ </testcase>
90
+ <testcase classname="PipedTextSelect calls the onClose handler when custom input is enabled and the user hits &quot;enter&quot; in the search query" name="PipedTextSelect calls the onClose handler when custom input is enabled and the user hits &quot;enter&quot; in the search query" time="0.527">
91
+ </testcase>
92
+ <testcase classname="PipedTextSelect does not call the onClose handler when custom input is disabled and the user hits &quot;enter&quot; in the search query" name="PipedTextSelect does not call the onClose handler when custom input is disabled and the user hits &quot;enter&quot; in the search query" time="0.704">
93
+ </testcase>
94
+ <testcase classname="PipedTextSelect displays piped text items provided by an async &quot;items&quot; function" name="PipedTextSelect displays piped text items provided by an async &quot;items&quot; function" time="0.635">
95
+ </testcase>
96
+ <testcase classname="PipedTextSelect displays piped text items provided by a non-async &quot;items&quot; function" name="PipedTextSelect displays piped text items provided by a non-async &quot;items&quot; function" time="0.588">
97
+ </testcase>
98
+ <testcase classname="PipedTextSelect displays loading error message if async piped text items function fails to resolve" name="PipedTextSelect displays loading error message if async piped text items function fails to resolve" time="0.615">
99
+ </testcase>
100
+ </testsuite>
101
+ </testsuites>
package/.bee DELETED
@@ -1,2 +0,0 @@
1
- # use node 14
2
- LANG_VERSION=14