codeceptjs 3.6.10 → 3.7.0-beta.10

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 (127) hide show
  1. package/README.md +89 -119
  2. package/bin/codecept.js +9 -2
  3. package/docs/webapi/clearCookie.mustache +1 -1
  4. package/lib/actor.js +66 -102
  5. package/lib/ai.js +130 -121
  6. package/lib/assert/empty.js +3 -5
  7. package/lib/assert/equal.js +4 -7
  8. package/lib/assert/include.js +4 -6
  9. package/lib/assert/throws.js +2 -4
  10. package/lib/assert/truth.js +2 -2
  11. package/lib/codecept.js +87 -83
  12. package/lib/command/check.js +186 -0
  13. package/lib/command/configMigrate.js +2 -4
  14. package/lib/command/definitions.js +8 -26
  15. package/lib/command/generate.js +10 -14
  16. package/lib/command/gherkin/snippets.js +10 -8
  17. package/lib/command/gherkin/steps.js +1 -1
  18. package/lib/command/info.js +1 -3
  19. package/lib/command/init.js +8 -12
  20. package/lib/command/interactive.js +2 -2
  21. package/lib/command/list.js +1 -1
  22. package/lib/command/run-multiple.js +12 -35
  23. package/lib/command/run-workers.js +5 -57
  24. package/lib/command/utils.js +5 -6
  25. package/lib/command/workers/runTests.js +68 -232
  26. package/lib/container.js +354 -237
  27. package/lib/data/context.js +10 -13
  28. package/lib/data/dataScenarioConfig.js +8 -8
  29. package/lib/data/dataTableArgument.js +6 -6
  30. package/lib/data/table.js +5 -11
  31. package/lib/effects.js +218 -0
  32. package/lib/els.js +158 -0
  33. package/lib/event.js +19 -17
  34. package/lib/heal.js +88 -80
  35. package/lib/helper/AI.js +2 -1
  36. package/lib/helper/ApiDataFactory.js +3 -6
  37. package/lib/helper/Appium.js +45 -51
  38. package/lib/helper/FileSystem.js +3 -3
  39. package/lib/helper/GraphQLDataFactory.js +3 -3
  40. package/lib/helper/JSONResponse.js +57 -37
  41. package/lib/helper/Nightmare.js +35 -53
  42. package/lib/helper/Playwright.js +211 -252
  43. package/lib/helper/Protractor.js +54 -77
  44. package/lib/helper/Puppeteer.js +139 -232
  45. package/lib/helper/REST.js +5 -17
  46. package/lib/helper/TestCafe.js +21 -44
  47. package/lib/helper/WebDriver.js +131 -169
  48. package/lib/helper/testcafe/testcafe-utils.js +26 -27
  49. package/lib/listener/emptyRun.js +55 -0
  50. package/lib/listener/exit.js +7 -10
  51. package/lib/listener/{retry.js → globalRetry.js} +5 -5
  52. package/lib/listener/globalTimeout.js +165 -0
  53. package/lib/listener/helpers.js +15 -15
  54. package/lib/listener/mocha.js +1 -1
  55. package/lib/listener/result.js +12 -0
  56. package/lib/listener/steps.js +20 -18
  57. package/lib/listener/store.js +20 -0
  58. package/lib/mocha/asyncWrapper.js +216 -0
  59. package/lib/{interfaces → mocha}/bdd.js +3 -3
  60. package/lib/mocha/cli.js +308 -0
  61. package/lib/mocha/factory.js +104 -0
  62. package/lib/{interfaces → mocha}/featureConfig.js +24 -12
  63. package/lib/{interfaces → mocha}/gherkin.js +26 -28
  64. package/lib/mocha/hooks.js +112 -0
  65. package/lib/mocha/index.js +12 -0
  66. package/lib/mocha/inject.js +29 -0
  67. package/lib/{interfaces → mocha}/scenarioConfig.js +21 -6
  68. package/lib/mocha/suite.js +81 -0
  69. package/lib/mocha/test.js +159 -0
  70. package/lib/mocha/types.d.ts +42 -0
  71. package/lib/mocha/ui.js +219 -0
  72. package/lib/output.js +82 -62
  73. package/lib/pause.js +155 -138
  74. package/lib/plugin/analyze.js +349 -0
  75. package/lib/plugin/autoDelay.js +6 -6
  76. package/lib/plugin/autoLogin.js +6 -7
  77. package/lib/plugin/commentStep.js +6 -1
  78. package/lib/plugin/coverage.js +10 -19
  79. package/lib/plugin/customLocator.js +3 -3
  80. package/lib/plugin/customReporter.js +52 -0
  81. package/lib/plugin/eachElement.js +1 -1
  82. package/lib/plugin/fakerTransform.js +1 -1
  83. package/lib/plugin/heal.js +36 -9
  84. package/lib/plugin/pageInfo.js +140 -0
  85. package/lib/plugin/retryFailedStep.js +4 -4
  86. package/lib/plugin/retryTo.js +18 -118
  87. package/lib/plugin/screenshotOnFail.js +17 -49
  88. package/lib/plugin/selenoid.js +15 -35
  89. package/lib/plugin/standardActingHelpers.js +4 -1
  90. package/lib/plugin/stepByStepReport.js +56 -17
  91. package/lib/plugin/stepTimeout.js +5 -12
  92. package/lib/plugin/subtitles.js +4 -4
  93. package/lib/plugin/tryTo.js +17 -107
  94. package/lib/plugin/wdio.js +8 -10
  95. package/lib/recorder.js +146 -125
  96. package/lib/rerun.js +43 -42
  97. package/lib/result.js +161 -0
  98. package/lib/secret.js +1 -1
  99. package/lib/step/base.js +228 -0
  100. package/lib/step/config.js +50 -0
  101. package/lib/step/func.js +46 -0
  102. package/lib/step/helper.js +50 -0
  103. package/lib/step/meta.js +99 -0
  104. package/lib/step/record.js +74 -0
  105. package/lib/step/retry.js +11 -0
  106. package/lib/step/section.js +55 -0
  107. package/lib/step.js +21 -332
  108. package/lib/steps.js +50 -0
  109. package/lib/store.js +10 -2
  110. package/lib/template/heal.js +2 -11
  111. package/lib/timeout.js +66 -0
  112. package/lib/utils.js +317 -216
  113. package/lib/within.js +73 -55
  114. package/lib/workers.js +259 -275
  115. package/package.json +56 -54
  116. package/typings/index.d.ts +175 -186
  117. package/typings/promiseBasedTypes.d.ts +164 -17
  118. package/typings/types.d.ts +284 -115
  119. package/lib/cli.js +0 -256
  120. package/lib/helper/ExpectHelper.js +0 -391
  121. package/lib/helper/SoftExpectHelper.js +0 -381
  122. package/lib/listener/artifacts.js +0 -19
  123. package/lib/listener/timeout.js +0 -109
  124. package/lib/mochaFactory.js +0 -113
  125. package/lib/plugin/debugErrors.js +0 -67
  126. package/lib/scenario.js +0 -224
  127. package/lib/ui.js +0 -236
@@ -5,6 +5,7 @@ const event = require('../event')
5
5
  const output = require('../output')
6
6
  const heal = require('../heal')
7
7
  const store = require('../store')
8
+ const container = require('../container')
8
9
 
9
10
  const defaultConfig = {
10
11
  healLimit: 2,
@@ -31,10 +32,7 @@ const defaultConfig = {
31
32
  module.exports = function (config = {}) {
32
33
  if (store.debugMode && !process.env.DEBUG) {
33
34
  event.dispatcher.on(event.test.failed, () => {
34
- output.plugin(
35
- 'heal',
36
- 'Healing is disabled in --debug mode, use DEBUG="codeceptjs:heal" to enable it in debug mode',
37
- )
35
+ output.plugin('heal', 'Healing is disabled in --debug mode, use DEBUG="codeceptjs:heal" to enable it in debug mode')
38
36
  })
39
37
  return
40
38
  }
@@ -48,21 +46,21 @@ module.exports = function (config = {}) {
48
46
 
49
47
  config = Object.assign(defaultConfig, config)
50
48
 
51
- event.dispatcher.on(event.test.before, (test) => {
49
+ event.dispatcher.on(event.test.before, test => {
52
50
  currentTest = test
53
51
  healedSteps = 0
54
52
  caughtError = null
55
53
  })
56
54
 
57
- event.dispatcher.on(event.step.started, (step) => (currentStep = step))
55
+ event.dispatcher.on(event.step.started, step => (currentStep = step))
58
56
 
59
- event.dispatcher.on(event.step.after, (step) => {
57
+ event.dispatcher.on(event.step.after, step => {
60
58
  if (isHealing) return
61
59
  if (healTries >= config.healLimit) return // out of limit
62
60
 
63
61
  if (!heal.hasCorrespondingRecipes(step)) return
64
62
 
65
- recorder.catchWithoutStop(async (err) => {
63
+ recorder.catchWithoutStop(async err => {
66
64
  isHealing = true
67
65
  if (caughtError === err) throw err // avoid double handling
68
66
  caughtError = err
@@ -99,7 +97,7 @@ module.exports = function (config = {}) {
99
97
 
100
98
  print(`${colors.bold(heal.fixes.length)} ${heal.fixes.length === 1 ? 'step was' : 'steps were'} healed`)
101
99
 
102
- const suggestions = heal.fixes.filter((fix) => fix.recipe && heal.recipes[fix.recipe].suggest)
100
+ const suggestions = heal.fixes.filter(fix => fix.recipe && heal.recipes[fix.recipe].suggest)
103
101
 
104
102
  if (!suggestions.length) return
105
103
 
@@ -118,4 +116,33 @@ module.exports = function (config = {}) {
118
116
  i++
119
117
  }
120
118
  })
119
+
120
+ event.dispatcher.on(event.workers.result, result => {
121
+ const { print } = output
122
+
123
+ const healedTests = Object.values(result.tests)
124
+ .flat()
125
+ .filter(test => test.notes.some(note => note.type === 'heal'))
126
+ if (!healedTests.length) return
127
+
128
+ setTimeout(() => {
129
+ print('')
130
+ print('===================')
131
+ print(colors.bold.green('Self-Healing Report:'))
132
+
133
+ print('')
134
+ print('Suggested changes:')
135
+ print('')
136
+
137
+ healedTests.forEach(test => {
138
+ print(`${colors.bold.magenta(test.title)}`)
139
+ test.notes
140
+ .filter(note => note.type === 'heal')
141
+ .forEach(note => {
142
+ print(note.text)
143
+ print('')
144
+ })
145
+ })
146
+ }, 0)
147
+ })
121
148
  }
@@ -0,0 +1,140 @@
1
+ const path = require('path')
2
+ const fs = require('fs')
3
+ const Container = require('../container')
4
+ const recorder = require('../recorder')
5
+ const event = require('../event')
6
+ const supportedHelpers = Container.STANDARD_ACTING_HELPERS
7
+ const { scanForErrorMessages } = require('../html')
8
+ const { output } = require('..')
9
+ const { humanizeString, ucfirst } = require('../utils')
10
+ const { testToFileName } = require('../mocha/test')
11
+ const defaultConfig = {
12
+ errorClasses: ['error', 'warning', 'alert', 'danger'],
13
+ browserLogs: ['error'],
14
+ }
15
+
16
+ /**
17
+ * Collects information from web page after each failed test and adds it to the test as an artifact.
18
+ * It is suggested to enable this plugin if you run tests on CI and you need to debug failed tests.
19
+ * This plugin can be paired with `analyze` plugin to provide more context.
20
+ *
21
+ * It collects URL, HTML errors (by classes), and browser logs.
22
+ *
23
+ * Enable this plugin in config:
24
+ *
25
+ * ```js
26
+ * plugins: {
27
+ * pageInfo: {
28
+ * enabled: true,
29
+ * }
30
+ * ```
31
+ *
32
+ * Additional config options:
33
+ *
34
+ * * `errorClasses` - list of classes to search for errors (default: `['error', 'warning', 'alert', 'danger']`)
35
+ * * `browserLogs` - list of types of errors to search for in browser logs (default: `['error']`)
36
+ *
37
+ */
38
+ module.exports = function (config = {}) {
39
+ const helpers = Container.helpers()
40
+ let helper
41
+
42
+ config = Object.assign(defaultConfig, config)
43
+
44
+ for (const helperName of supportedHelpers) {
45
+ if (Object.keys(helpers).indexOf(helperName) > -1) {
46
+ helper = helpers[helperName]
47
+ }
48
+ }
49
+
50
+ if (!helper) return // no helpers for screenshot
51
+
52
+ event.dispatcher.on(event.test.failed, test => {
53
+ const pageState = {}
54
+
55
+ recorder.add('URL of failed test', async () => {
56
+ try {
57
+ const url = await helper.grabCurrentUrl()
58
+ pageState.url = url
59
+ } catch (err) {
60
+ // not really needed
61
+ }
62
+ })
63
+ recorder.add('HTML snapshot failed test', async () => {
64
+ try {
65
+ const html = await helper.grabHTMLFrom('body')
66
+
67
+ if (!html) return
68
+
69
+ const errors = scanForErrorMessages(html, config.errorClasses)
70
+ if (errors.length) {
71
+ output.debug('Detected errors in HTML code')
72
+ errors.forEach(error => output.debug(error))
73
+ pageState.htmlErrors = errors
74
+ }
75
+ } catch (err) {
76
+ // not really needed
77
+ }
78
+ })
79
+
80
+ recorder.add('Browser logs for failed test', async () => {
81
+ try {
82
+ const logs = await helper.grabBrowserLogs()
83
+
84
+ if (!logs) return
85
+
86
+ pageState.browserErrors = getBrowserErrors(logs, config.browserLogs)
87
+ } catch (err) {
88
+ // not really needed
89
+ }
90
+ })
91
+
92
+ recorder.add('Save page info', () => {
93
+ test.addNote('pageInfo', pageStateToMarkdown(pageState))
94
+
95
+ const pageStateFileName = path.join(global.output_dir, `${testToFileName(test)}.pageInfo.md`)
96
+ fs.writeFileSync(pageStateFileName, pageStateToMarkdown(pageState))
97
+ test.artifacts.pageInfo = pageStateFileName
98
+ return pageState
99
+ })
100
+ })
101
+ }
102
+
103
+ function pageStateToMarkdown(pageState) {
104
+ let markdown = ''
105
+
106
+ for (const [key, value] of Object.entries(pageState)) {
107
+ if (!value) continue
108
+ let result = ''
109
+
110
+ if (Array.isArray(value)) {
111
+ result = value.map(v => `- ${JSON.stringify(v, null, 2)}`).join('\n')
112
+ } else if (typeof value === 'string') {
113
+ result = `${value}`
114
+ } else {
115
+ result = JSON.stringify(value, null, 2)
116
+ }
117
+
118
+ if (!result.trim()) continue
119
+
120
+ markdown += `### ${ucfirst(humanizeString(key))}\n\n`
121
+ markdown += result
122
+ markdown += '\n\n'
123
+ }
124
+
125
+ return markdown
126
+ }
127
+
128
+ function getBrowserErrors(logs, type = ['error']) {
129
+ // Playwright & WebDriver console messages
130
+ let errors = logs
131
+ .map(log => {
132
+ if (typeof log === 'string') return log
133
+ if (!log.type) return null
134
+ return { type: log.type(), text: log.text() }
135
+ })
136
+ .filter(l => l && (typeof l === 'string' || type.includes(l.type)))
137
+ .map(l => (typeof l === 'string' ? l : l.text))
138
+
139
+ return errors
140
+ }
@@ -76,14 +76,14 @@ const defaultConfig = {
76
76
  * ```
77
77
  *
78
78
  */
79
- module.exports = (config) => {
79
+ module.exports = config => {
80
80
  config = Object.assign(defaultConfig, config)
81
81
  config.ignoredSteps = config.ignoredSteps.concat(config.defaultIgnoredSteps)
82
82
  const customWhen = config.when
83
83
 
84
84
  let enableRetry = false
85
85
 
86
- const when = (err) => {
86
+ const when = err => {
87
87
  if (!enableRetry) return
88
88
  const store = require('../store')
89
89
  if (store.debugMode) return false
@@ -92,7 +92,7 @@ module.exports = (config) => {
92
92
  }
93
93
  config.when = when
94
94
 
95
- event.dispatcher.on(event.step.started, (step) => {
95
+ event.dispatcher.on(event.step.started, step => {
96
96
  if (process.env.TRY_TO === 'true') {
97
97
  log('Info: RetryFailedStep plugin is disabled inside tryTo block')
98
98
  return
@@ -112,7 +112,7 @@ module.exports = (config) => {
112
112
  enableRetry = false
113
113
  })
114
114
 
115
- event.dispatcher.on(event.test.before, (test) => {
115
+ event.dispatcher.on(event.test.before, test => {
116
116
  if (test && test.disableRetryFailedStep) return // disable retry when a test is not active
117
117
  // this env var is used to set the retries inside _before() block of helpers
118
118
  process.env.FAILED_STEP_RETRIES = config.retries
@@ -1,123 +1,23 @@
1
- const recorder = require('../recorder')
2
- const { debug } = require('../output')
1
+ const { retryTo } = require('../effects')
3
2
 
4
- const defaultConfig = {
5
- registerGlobal: true,
6
- pollInterval: 200,
7
- }
8
-
9
- /**
10
- *
11
- *
12
- * Adds global `retryTo` which retries steps a few times before failing.
13
- *
14
- * Enable this plugin in `codecept.conf.js` (enabled by default for new setups):
15
- *
16
- * ```js
17
- * plugins: {
18
- * retryTo: {
19
- * enabled: true
20
- * }
21
- * }
22
- * ```
23
- *
24
- * Use it in your tests:
25
- *
26
- * ```js
27
- * // retry these steps 5 times before failing
28
- * await retryTo((tryNum) => {
29
- * I.switchTo('#editor frame');
30
- * I.click('Open');
31
- * I.see('Opened')
32
- * }, 5);
33
- * ```
34
- * Set polling interval as 3rd argument (200ms by default):
35
- *
36
- * ```js
37
- * // retry these steps 5 times before failing
38
- * await retryTo((tryNum) => {
39
- * I.switchTo('#editor frame');
40
- * I.click('Open');
41
- * I.see('Opened')
42
- * }, 5, 100);
43
- * ```
44
- *
45
- * Default polling interval can be changed in a config:
46
- *
47
- * ```js
48
- * plugins: {
49
- * retryTo: {
50
- * enabled: true,
51
- * pollInterval: 500,
52
- * }
53
- * }
54
- * ```
55
- *
56
- * Disables retryFailedStep plugin for steps inside a block;
57
- *
58
- * Use this plugin if:
59
- *
60
- * * you need repeat a set of actions in flaky tests
61
- * * iframe was not rendered and you need to retry switching to it
62
- *
63
- *
64
- * #### Configuration
65
- *
66
- * * `pollInterval` - default interval between retries in ms. 200 by default.
67
- * * `registerGlobal` - to register `retryTo` function globally, true by default
68
- *
69
- * If `registerGlobal` is false you can use retryTo from the plugin:
70
- *
71
- * ```js
72
- * const retryTo = codeceptjs.container.plugins('retryTo');
73
- * ```
74
- *
75
- */
76
3
  module.exports = function (config) {
77
- config = Object.assign(defaultConfig, config)
78
- function retryTo(callback, maxTries, pollInterval = config.pollInterval) {
79
- return new Promise((done, reject) => {
80
- let tries = 1
81
-
82
- function handleRetryException(err) {
83
- recorder.throw(err)
84
- reject(err)
85
- }
86
-
87
- const tryBlock = async () => {
88
- tries++
89
- recorder.session.start(`retryTo ${tries}`)
90
- try {
91
- await callback(tries)
92
- } catch (err) {
93
- handleRetryException(err)
94
- }
95
-
96
- // Call done if no errors
97
- recorder.add(() => {
98
- recorder.session.restore(`retryTo ${tries}`)
99
- done(null)
100
- })
101
-
102
- // Catch errors and retry
103
- recorder.session.catch((err) => {
104
- recorder.session.restore(`retryTo ${tries}`)
105
- if (tries <= maxTries) {
106
- debug(`Error ${err}... Retrying`)
107
- recorder.add(`retryTo ${tries}`, () => setTimeout(tryBlock, pollInterval))
108
- } else {
109
- // if maxTries reached
110
- handleRetryException(err)
111
- }
112
- })
113
- }
114
-
115
- recorder.add('retryTo', tryBlock).catch((err) => {
116
- console.error('An error occurred:', err)
117
- done(null)
118
- })
119
- })
120
- }
4
+ console.log(`
5
+ Deprecation Warning: 'retryTo' has been moved to the effects module.
6
+ You should update your tests to use it as follows:
7
+
8
+ \`\`\`javascript
9
+ const { retryTo } = require('codeceptjs/effects');
10
+
11
+ // Example: Retry these steps 5 times before failing
12
+ await retryTo((tryNum) => {
13
+ I.switchTo('#editor frame');
14
+ I.click('Open');
15
+ I.see('Opened');
16
+ }, 5);
17
+ \`\`\`
18
+
19
+ For more details, refer to the documentation.
20
+ `)
121
21
 
122
22
  if (config.registerGlobal) {
123
23
  global.retryTo = retryTo
@@ -5,8 +5,9 @@ const Container = require('../container')
5
5
  const recorder = require('../recorder')
6
6
  const event = require('../event')
7
7
  const output = require('../output')
8
- const { fileExists, clearString } = require('../utils')
8
+ const { fileExists } = require('../utils')
9
9
  const Codeceptjs = require('../index')
10
+ const { testToFileName } = require('../mocha/test')
10
11
 
11
12
  const defaultConfig = {
12
13
  uniqueScreenshotNames: false,
@@ -14,7 +15,7 @@ const defaultConfig = {
14
15
  fullPageScreenshots: false,
15
16
  }
16
17
 
17
- const supportedHelpers = require('./standardActingHelpers')
18
+ const supportedHelpers = Container.STANDARD_ACTING_HELPERS
18
19
 
19
20
  /**
20
21
  * Creates screenshot on failure. Screenshot is saved into `output` directory.
@@ -63,9 +64,7 @@ module.exports = function (config) {
63
64
  }
64
65
 
65
66
  if (Codeceptjs.container.mocha()) {
66
- options.reportDir =
67
- Codeceptjs.container.mocha().options.reporterOptions &&
68
- Codeceptjs.container.mocha().options.reporterOptions.reportDir
67
+ options.reportDir = Codeceptjs.container.mocha()?.options?.reporterOptions && Codeceptjs.container.mocha()?.options?.reporterOptions?.reportDir
69
68
  }
70
69
 
71
70
  if (options.disableScreenshots) {
@@ -73,25 +72,19 @@ module.exports = function (config) {
73
72
  return
74
73
  }
75
74
 
76
- event.dispatcher.on(event.test.failed, (test) => {
77
- if (test.ctx?._runnable.title.includes('hook: ')) {
78
- output.plugin(
79
- 'screenshotOnFail',
80
- 'BeforeSuite/AfterSuite do not have any access to the browser, hence it could not take screenshot.',
81
- )
75
+ event.dispatcher.on(event.test.failed, (test, _err, hookName) => {
76
+ if (hookName === 'BeforeSuite' || hookName === 'AfterSuite') {
77
+ // no browser here
82
78
  return
83
79
  }
80
+
84
81
  recorder.add(
85
82
  'screenshot of failed test',
86
83
  async () => {
87
- let fileName = clearString(test.title)
88
84
  const dataType = 'image/png'
89
85
  // This prevents data driven to be included in the failed screenshot file name
90
- if (fileName.indexOf('{') !== -1) {
91
- fileName = fileName.substr(0, fileName.indexOf('{') - 3).trim()
92
- }
93
- if (test.ctx && test.ctx.test && test.ctx.test.type === 'hook')
94
- fileName = clearString(`${test.title}_${test.ctx.test.title}`)
86
+ let fileName = testToFileName(test)
87
+
95
88
  if (options.uniqueScreenshotNames && test) {
96
89
  const uuid = _getUUID(test)
97
90
  fileName = `${fileName.substring(0, 10)}_${uuid}.failed.png`
@@ -112,34 +105,20 @@ module.exports = function (config) {
112
105
 
113
106
  if (!test.artifacts) test.artifacts = {}
114
107
  test.artifacts.screenshot = path.join(global.output_dir, fileName)
115
- if (
116
- Container.mocha().options.reporterOptions['mocha-junit-reporter'] &&
117
- Container.mocha().options.reporterOptions['mocha-junit-reporter'].options.attachments
118
- ) {
108
+ if (Container.mocha().options.reporterOptions['mocha-junit-reporter'] && Container.mocha().options.reporterOptions['mocha-junit-reporter'].options.attachments) {
119
109
  test.attachments = [path.join(global.output_dir, fileName)]
120
110
  }
121
111
 
122
112
  const allureReporter = Container.plugins('allure')
123
113
  if (allureReporter) {
124
- allureReporter.addAttachment(
125
- 'Main session - Last Seen Screenshot',
126
- fs.readFileSync(path.join(global.output_dir, fileName)),
127
- dataType,
128
- )
114
+ allureReporter.addAttachment('Main session - Last Seen Screenshot', fs.readFileSync(path.join(global.output_dir, fileName)), dataType)
129
115
 
130
116
  if (helper.activeSessionName) {
131
117
  const sessions = helper.sessionPages || helper.sessionWindows
132
118
  for (const sessionName in sessions) {
133
119
  const screenshotFileName = `${sessionName}_${fileName}`
134
- test.artifacts[`${sessionName.replace(/ /g, '_')}_screenshot`] = path.join(
135
- global.output_dir,
136
- screenshotFileName,
137
- )
138
- allureReporter.addAttachment(
139
- `${sessionName} - Last Seen Screenshot`,
140
- fs.readFileSync(path.join(global.output_dir, screenshotFileName)),
141
- dataType,
142
- )
120
+ test.artifacts[`${sessionName.replace(/ /g, '_')}_screenshot`] = path.join(global.output_dir, screenshotFileName)
121
+ allureReporter.addAttachment(`${sessionName} - Last Seen Screenshot`, fs.readFileSync(path.join(global.output_dir, screenshotFileName)), dataType)
143
122
  }
144
123
  }
145
124
  }
@@ -150,14 +129,7 @@ module.exports = function (config) {
150
129
  }
151
130
  } catch (err) {
152
131
  output.plugin(err)
153
- if (
154
- err &&
155
- err.type &&
156
- err.type === 'RuntimeError' &&
157
- err.message &&
158
- (err.message.indexOf('was terminated due to') > -1 ||
159
- err.message.indexOf('no such window: target window already closed') > -1)
160
- ) {
132
+ if (err && err.type && err.type === 'RuntimeError' && err.message && (err.message.indexOf('was terminated due to') > -1 || err.message.indexOf('no such window: target window already closed') > -1)) {
161
133
  output.log(`Can't make screenshot, ${err}`)
162
134
  helper.isRunning = false
163
135
  }
@@ -168,12 +140,8 @@ module.exports = function (config) {
168
140
  })
169
141
 
170
142
  function _getUUID(test) {
171
- if (test.uuid) {
172
- return test.uuid
173
- }
174
-
175
- if (test.ctx && test.ctx.test.uuid) {
176
- return test.ctx.test.uuid
143
+ if (test.uid) {
144
+ return test.uid
177
145
  }
178
146
 
179
147
  return Math.floor(new Date().getTime() / 1000)
@@ -41,12 +41,7 @@ const dockerCreateScriptArr = [
41
41
  'aerokube/selenoid:latest-release -log-output-dir /opt/selenoid/logs',
42
42
  ]
43
43
 
44
- const dockerImageCheckScript = [
45
- 'docker images',
46
- "--filter reference='selenoid/video-recorder'",
47
- "--filter reference='selenoid/chrome:latest'",
48
- "--filter reference='selenoid/firefox:latest'",
49
- ].join(' ')
44
+ const dockerImageCheckScript = ['docker images', "--filter reference='selenoid/video-recorder'", "--filter reference='selenoid/chrome:latest'", "--filter reference='selenoid/firefox:latest'"].join(' ')
50
45
 
51
46
  let dockerCreateScript = dockerCreateScriptArr.join(' ')
52
47
  let dockerStartScript = 'docker start $name$'
@@ -56,8 +51,8 @@ let seleniumUrl = 'http://localhost:$port$'
56
51
  const supportedHelpers = ['WebDriver']
57
52
  const SELENOID_START_TIMEOUT = 2000
58
53
  const SELENOID_STOP_TIMEOUT = 10000
59
- const wait = (time) =>
60
- new Promise((res) => {
54
+ const wait = time =>
55
+ new Promise(res => {
61
56
  setTimeout(() => {
62
57
  // @ts-ignore
63
58
  res()
@@ -179,7 +174,7 @@ const wait = (time) =>
179
174
  *
180
175
  */
181
176
 
182
- const selenoid = (config) => {
177
+ const selenoid = config => {
183
178
  const helpers = container.helpers()
184
179
  let helperName
185
180
 
@@ -194,14 +189,7 @@ const selenoid = (config) => {
194
189
  return // no helpers for Selenoid
195
190
  }
196
191
 
197
- const {
198
- autoStart,
199
- name = 'selenoid',
200
- deletePassed = true,
201
- additionalParams = '',
202
- autoCreate = true,
203
- port = 4444,
204
- } = config
192
+ const { autoStart, name = 'selenoid', deletePassed = true, additionalParams = '', autoCreate = true, port = 4444 } = config
205
193
  const passedTests = []
206
194
 
207
195
  recorder.startUnlessRunning()
@@ -213,7 +201,7 @@ const selenoid = (config) => {
213
201
  output.debug('Staring Selenoid... ')
214
202
  return createAndStart(autoCreate)
215
203
  .then(() => output.debug('Selenoid started'))
216
- .catch((err) => {
204
+ .catch(err => {
217
205
  throw new Error(err.stack)
218
206
  })
219
207
  })
@@ -226,7 +214,7 @@ const selenoid = (config) => {
226
214
  .then(() => deletePassedTests(passedTests))
227
215
  .then(stopSelenoid)
228
216
  .then(() => output.debug('Selenoid stopped'))
229
- .catch((err) => {
217
+ .catch(err => {
230
218
  throw new Error(err.stack)
231
219
  })
232
220
  })
@@ -241,7 +229,7 @@ const selenoid = (config) => {
241
229
  }
242
230
  })
243
231
 
244
- event.dispatcher.on(event.test.before, (test) => {
232
+ event.dispatcher.on(event.test.before, test => {
245
233
  switch (helperName) {
246
234
  case 'WebDriver':
247
235
  setTestConfigForWebdriver(test)
@@ -250,7 +238,7 @@ const selenoid = (config) => {
250
238
  })
251
239
 
252
240
  if (config.enableVideo) {
253
- event.dispatcher.on(event.test.passed, (test) => {
241
+ event.dispatcher.on(event.test.passed, test => {
254
242
  if (deletePassed) {
255
243
  passedTests.push(test.title)
256
244
  } else {
@@ -258,7 +246,7 @@ const selenoid = (config) => {
258
246
  }
259
247
  })
260
248
 
261
- event.dispatcher.on(event.test.failed, (test) => {
249
+ event.dispatcher.on(event.test.failed, test => {
262
250
  test.artifacts.video = videoSaved(test)
263
251
  })
264
252
  }
@@ -312,16 +300,12 @@ const pullImage = async () => {
312
300
  console.time('Pulled containers')
313
301
  if (!stdout.includes('selenoid/video-recorder')) {
314
302
  output.debug('Pulling selenoid/video-recorder...')
315
- resultPromise = exec('docker pull selenoid/video-recorder:latest-release').then(() =>
316
- output.debug('Pulled in selenoid/video-recorder'),
317
- )
303
+ resultPromise = exec('docker pull selenoid/video-recorder:latest-release').then(() => output.debug('Pulled in selenoid/video-recorder'))
318
304
  pulls.push(resultPromise)
319
305
  }
320
306
  if (!stdout.includes('selenoid/chrome')) {
321
307
  output.debug('Pulling selenoid/chrome...')
322
- resultPromise = exec('docker pull selenoid/chrome:latest').then(() =>
323
- output.debug('Pulled in selenoid/video-recorder'),
324
- )
308
+ resultPromise = exec('docker pull selenoid/chrome:latest').then(() => output.debug('Pulled in selenoid/video-recorder'))
325
309
  pulls.push(resultPromise)
326
310
  }
327
311
  if (!stdout.includes('selenoid/firefox')) {
@@ -341,16 +325,12 @@ function createAndStart(autoCreate) {
341
325
  }
342
326
 
343
327
  function deletePassedTests(passedTests) {
344
- const deleteVideoPromiseList = passedTests
345
- .map(clearString)
346
- .map((test) => axios.delete(`${seleniumUrl}/video/${test}.mp4`))
347
- const deleteLogPromiseList = passedTests
348
- .map(clearString)
349
- .map((test) => axios.delete(`${seleniumUrl}/logs/${test}.log`))
328
+ const deleteVideoPromiseList = passedTests.map(clearString).map(test => axios.delete(`${seleniumUrl}/video/${test}.mp4`))
329
+ const deleteLogPromiseList = passedTests.map(clearString).map(test => axios.delete(`${seleniumUrl}/logs/${test}.log`))
350
330
 
351
331
  return Promise.all(deleteVideoPromiseList.concat(deleteLogPromiseList))
352
332
  .then(() => output.debug('Deleted videos and logs for all passed tests'))
353
- .catch((err) => output.error(`Error while deleting video and log files ${err.stack}`))
333
+ .catch(err => output.error(`Error while deleting video and log files ${err.stack}`))
354
334
  }
355
335
 
356
336
  function setOptionsForWebdriver(config) {
@@ -1,3 +1,6 @@
1
- const standardActingHelpers = ['Playwright', 'WebDriver', 'Puppeteer', 'Appium', 'TestCafe']
1
+ const Container = require('../container')
2
+ // due to using this in internal tooling we won't post deprecation warning
3
+ // but please switch to Container.STANDARD_ACTING_HELPERS
4
+ const standardActingHelpers = Container.STANDARD_ACTING_HELPERS
2
5
 
3
6
  module.exports = standardActingHelpers