@hexonet/semantic-release-whmcs 3.0.2 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. package/.eslintrc.js +13 -11
  2. package/.github/workflows/pull-request.yml +47 -0
  3. package/.github/workflows/push.yml +76 -0
  4. package/.releaserc.json +20 -23
  5. package/HISTORY.md +30 -0
  6. package/README.md +5 -5
  7. package/coverage/base.css +224 -0
  8. package/coverage/block-navigation.js +87 -0
  9. package/coverage/coverage-final.json +11 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/index.html +131 -0
  12. package/coverage/lib/definitions/errors.js.html +136 -0
  13. package/coverage/lib/definitions/index.html +116 -0
  14. package/coverage/lib/delete-marketplace-version.js.html +400 -0
  15. package/coverage/lib/get-error.js.html +106 -0
  16. package/coverage/lib/get-github-releases.js.html +190 -0
  17. package/coverage/lib/index.html +236 -0
  18. package/coverage/lib/publish.js.html +490 -0
  19. package/coverage/lib/puppet.js.html +271 -0
  20. package/coverage/lib/resolve-config.js.html +112 -0
  21. package/coverage/lib/scrape-marketplace-versions.js.html +322 -0
  22. package/coverage/lib/set-compatible-versions.js.html +376 -0
  23. package/coverage/lib/verify.js.html +145 -0
  24. package/coverage/prettify.css +1 -0
  25. package/coverage/prettify.js +2 -0
  26. package/coverage/sort-arrow-sprite.png +0 -0
  27. package/coverage/sorter.js +196 -0
  28. package/index.js +11 -9
  29. package/lib/definitions/errors.js +6 -3
  30. package/lib/delete-marketplace-version.js +7 -36
  31. package/lib/get-error.js +1 -1
  32. package/lib/get-github-releases.js +10 -8
  33. package/lib/publish.js +97 -105
  34. package/lib/puppet.js +62 -0
  35. package/lib/resolve-config.js +2 -2
  36. package/lib/scrape-marketplace-versions.js +5 -34
  37. package/lib/set-compatible-versions.js +6 -34
  38. package/package.json +20 -21
  39. package/whmcs.js +1 -2
  40. package/.github/workflows/release.yml +0 -56
  41. package/test/publish.test.js +0 -78
  42. package/test/verify.test.js +0 -54
@@ -0,0 +1,196 @@
1
+ /* eslint-disable */
2
+ var addSorting = (function() {
3
+ 'use strict';
4
+ var cols,
5
+ currentSort = {
6
+ index: 0,
7
+ desc: false
8
+ };
9
+
10
+ // returns the summary table element
11
+ function getTable() {
12
+ return document.querySelector('.coverage-summary');
13
+ }
14
+ // returns the thead element of the summary table
15
+ function getTableHeader() {
16
+ return getTable().querySelector('thead tr');
17
+ }
18
+ // returns the tbody element of the summary table
19
+ function getTableBody() {
20
+ return getTable().querySelector('tbody');
21
+ }
22
+ // returns the th element for nth column
23
+ function getNthColumn(n) {
24
+ return getTableHeader().querySelectorAll('th')[n];
25
+ }
26
+
27
+ function onFilterInput() {
28
+ const searchValue = document.getElementById('fileSearch').value;
29
+ const rows = document.getElementsByTagName('tbody')[0].children;
30
+ for (let i = 0; i < rows.length; i++) {
31
+ const row = rows[i];
32
+ if (
33
+ row.textContent
34
+ .toLowerCase()
35
+ .includes(searchValue.toLowerCase())
36
+ ) {
37
+ row.style.display = '';
38
+ } else {
39
+ row.style.display = 'none';
40
+ }
41
+ }
42
+ }
43
+
44
+ // loads the search box
45
+ function addSearchBox() {
46
+ var template = document.getElementById('filterTemplate');
47
+ var templateClone = template.content.cloneNode(true);
48
+ templateClone.getElementById('fileSearch').oninput = onFilterInput;
49
+ template.parentElement.appendChild(templateClone);
50
+ }
51
+
52
+ // loads all columns
53
+ function loadColumns() {
54
+ var colNodes = getTableHeader().querySelectorAll('th'),
55
+ colNode,
56
+ cols = [],
57
+ col,
58
+ i;
59
+
60
+ for (i = 0; i < colNodes.length; i += 1) {
61
+ colNode = colNodes[i];
62
+ col = {
63
+ key: colNode.getAttribute('data-col'),
64
+ sortable: !colNode.getAttribute('data-nosort'),
65
+ type: colNode.getAttribute('data-type') || 'string'
66
+ };
67
+ cols.push(col);
68
+ if (col.sortable) {
69
+ col.defaultDescSort = col.type === 'number';
70
+ colNode.innerHTML =
71
+ colNode.innerHTML + '<span class="sorter"></span>';
72
+ }
73
+ }
74
+ return cols;
75
+ }
76
+ // attaches a data attribute to every tr element with an object
77
+ // of data values keyed by column name
78
+ function loadRowData(tableRow) {
79
+ var tableCols = tableRow.querySelectorAll('td'),
80
+ colNode,
81
+ col,
82
+ data = {},
83
+ i,
84
+ val;
85
+ for (i = 0; i < tableCols.length; i += 1) {
86
+ colNode = tableCols[i];
87
+ col = cols[i];
88
+ val = colNode.getAttribute('data-value');
89
+ if (col.type === 'number') {
90
+ val = Number(val);
91
+ }
92
+ data[col.key] = val;
93
+ }
94
+ return data;
95
+ }
96
+ // loads all row data
97
+ function loadData() {
98
+ var rows = getTableBody().querySelectorAll('tr'),
99
+ i;
100
+
101
+ for (i = 0; i < rows.length; i += 1) {
102
+ rows[i].data = loadRowData(rows[i]);
103
+ }
104
+ }
105
+ // sorts the table using the data for the ith column
106
+ function sortByIndex(index, desc) {
107
+ var key = cols[index].key,
108
+ sorter = function(a, b) {
109
+ a = a.data[key];
110
+ b = b.data[key];
111
+ return a < b ? -1 : a > b ? 1 : 0;
112
+ },
113
+ finalSorter = sorter,
114
+ tableBody = document.querySelector('.coverage-summary tbody'),
115
+ rowNodes = tableBody.querySelectorAll('tr'),
116
+ rows = [],
117
+ i;
118
+
119
+ if (desc) {
120
+ finalSorter = function(a, b) {
121
+ return -1 * sorter(a, b);
122
+ };
123
+ }
124
+
125
+ for (i = 0; i < rowNodes.length; i += 1) {
126
+ rows.push(rowNodes[i]);
127
+ tableBody.removeChild(rowNodes[i]);
128
+ }
129
+
130
+ rows.sort(finalSorter);
131
+
132
+ for (i = 0; i < rows.length; i += 1) {
133
+ tableBody.appendChild(rows[i]);
134
+ }
135
+ }
136
+ // removes sort indicators for current column being sorted
137
+ function removeSortIndicators() {
138
+ var col = getNthColumn(currentSort.index),
139
+ cls = col.className;
140
+
141
+ cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
142
+ col.className = cls;
143
+ }
144
+ // adds sort indicators for current column being sorted
145
+ function addSortIndicators() {
146
+ getNthColumn(currentSort.index).className += currentSort.desc
147
+ ? ' sorted-desc'
148
+ : ' sorted';
149
+ }
150
+ // adds event listeners for all sorter widgets
151
+ function enableUI() {
152
+ var i,
153
+ el,
154
+ ithSorter = function ithSorter(i) {
155
+ var col = cols[i];
156
+
157
+ return function() {
158
+ var desc = col.defaultDescSort;
159
+
160
+ if (currentSort.index === i) {
161
+ desc = !currentSort.desc;
162
+ }
163
+ sortByIndex(i, desc);
164
+ removeSortIndicators();
165
+ currentSort.index = i;
166
+ currentSort.desc = desc;
167
+ addSortIndicators();
168
+ };
169
+ };
170
+ for (i = 0; i < cols.length; i += 1) {
171
+ if (cols[i].sortable) {
172
+ // add the click event handler on the th so users
173
+ // dont have to click on those tiny arrows
174
+ el = getNthColumn(i).querySelector('.sorter').parentElement;
175
+ if (el.addEventListener) {
176
+ el.addEventListener('click', ithSorter(i));
177
+ } else {
178
+ el.attachEvent('onclick', ithSorter(i));
179
+ }
180
+ }
181
+ }
182
+ }
183
+ // adds sorting functionality to the UI
184
+ return function() {
185
+ if (!getTable()) {
186
+ return;
187
+ }
188
+ cols = loadColumns();
189
+ loadData();
190
+ addSearchBox();
191
+ addSortIndicators();
192
+ enableUI();
193
+ };
194
+ })();
195
+
196
+ window.addEventListener('load', addSorting);
package/index.js CHANGED
@@ -32,17 +32,19 @@ async function publish (pluginConfig, context) {
32
32
  async function syncVersions (pluginConfig, context) {
33
33
  await verifyConditions(pluginConfig, context)
34
34
  const releases = await githubReleases(pluginConfig, context)
35
- const versions = await marketplaceVersions(pluginConfig, context)
36
35
 
37
- for (const release of releases) {
38
- if (!versions.includes(release.name.substring(1))) {
39
- context.nextRelease = {
40
- version: release.name.substring(1),
41
- notes: release.body,
42
- releaseDate: release.published_at
36
+ if (releases && releases.length) {
37
+ const versions = await marketplaceVersions(pluginConfig, context)
38
+ for (const release of releases) {
39
+ if (!versions.includes(release.name.substring(1))) {
40
+ context.nextRelease = {
41
+ version: release.name.substring(1),
42
+ notes: release.body,
43
+ releaseDate: release.published_at
44
+ }
45
+ console.log(`Adding missing version ${context.nextRelease.version}`)
46
+ await publish(pluginConfig, context)
43
47
  }
44
- console.log(`Adding missing version ${context.nextRelease.version}`)
45
- await publish(pluginConfig, context)
46
48
  }
47
49
  }
48
50
  }
@@ -1,14 +1,17 @@
1
1
  module.exports = {
2
2
  EWHMCSNOCREDENTIALS: () => ({
3
3
  message: 'No WHMCS Marketplace credentials specified.',
4
- details: 'WHMCS Marketplace credentails have to be set in the `WHMCS_LOGIN` and `WHMCS_PASSWORD` environment variables on your CI environment.'
4
+ details:
5
+ 'WHMCS Marketplace credentails have to be set in the `WHMCS_LOGIN` and `WHMCS_PASSWORD` environment variables on your CI environment.'
5
6
  }),
6
7
  EWHMCSNOPRODUCTID: () => ({
7
8
  message: 'No WHMCS Marketplace Product ID specified.',
8
- details: 'The product id of your listed product at the WHMCS Marketplace has to be set in the `WHMCS_PRODUCTID` environment variable on your CI environment. You\'ll find that number in url when visiting the product page in WHMCS Marketplace.'
9
+ details:
10
+ "The product id of your listed product at the WHMCS Marketplace has to be set in the `WHMCS_PRODUCTID` environment variable on your CI environment. You'll find that number in url when visiting the product page in WHMCS Marketplace."
9
11
  }),
10
12
  EWHMCSINVALIDPRODUCTID: () => ({
11
13
  message: 'Invalid WHMCS Marketplace Product ID specified.',
12
- details: 'The product id of your listed product at the WHMCS Marketplace has to be set in the `WHMCS_PRODUCTID` environment variable on your CI environment. You\'ll find that number in url when visiting the product page in WHMCS Marketplace.'
14
+ details:
15
+ "The product id of your listed product at the WHMCS Marketplace has to be set in the `WHMCS_PRODUCTID` environment variable on your CI environment. You'll find that number in url when visiting the product page in WHMCS Marketplace."
13
16
  })
14
17
  }
@@ -1,12 +1,6 @@
1
1
  const debug = require('debug')('semantic-release:whmcs')
2
2
  const resolveConfig = require('./resolve-config')
3
- const puppeteer = require('puppeteer')
4
- const gotoOpts = {
5
- waitUntil: ['load', 'domcontentloaded'],
6
- timeout: 240000
7
- }
8
- const navOpts = { waitUntil: 'networkidle0', timeout: 240000 }
9
- const selectorOpts = { timeout: 10000 }
3
+ const puppet = require('./puppet')
10
4
 
11
5
  /**
12
6
  * A method to publish the module update on whmcs market place
@@ -25,6 +19,7 @@ module.exports = async (pluginConfig, context) => {
25
19
 
26
20
  let success = true
27
21
  const { whmcsLOGIN, whmcsPASSWORD, whmcsPRODUCTID, DEBUG } = resolveConfig(context)
22
+ const { gotoOpts, navOpts, selectorOpts, page } = await puppet(DEBUG, logger)
28
23
 
29
24
  debug(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`)
30
25
  logger.log(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`)
@@ -35,34 +30,8 @@ module.exports = async (pluginConfig, context) => {
35
30
  // strip markdown links from notes as not allowed to keep
36
31
  const wmbase = 'https://marketplace.whmcs.com'
37
32
  let url = `${wmbase}/user/login`
38
- const browser = await puppeteer.launch({
39
- headless: !DEBUG,
40
- defaultViewport: null, // automatically full-sized
41
- args: [
42
- '--incognito',
43
- '--start-maximized',
44
- '--no-sandbox',
45
- '--disable-setuid-sandbox',
46
- '--disable-infobars',
47
- '--ignore-certifcate-errors',
48
- '--ignore-certifcate-errors-spki-list',
49
- '--ignoreHTTPSErrors=true',
50
- '--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"'
51
- ]
52
- })
53
- const [page] = await browser.pages()
54
33
 
55
34
  try {
56
- await page.setRequestInterception(true)
57
- page.on('request', request => {
58
- if (/^(image|stylesheet|other)$/i.test(request.resourceType())) {
59
- request.abort()
60
- } else {
61
- request.continue()
62
- }
63
- })
64
-
65
- await page.setJavaScriptEnabled(true)
66
35
  await page.goto(url, gotoOpts)
67
36
  // do login
68
37
  const selector = 'div.login-leftcol form button[type="submit"]'
@@ -72,6 +41,7 @@ module.exports = async (pluginConfig, context) => {
72
41
  await page.type('#password', whmcsPASSWORD)
73
42
  debug('WHMCS Marketplace credentials entered')
74
43
  const nav = page.waitForNavigation(navOpts)
44
+ await page.hover(selector)
75
45
  await page.click(selector)
76
46
  await nav
77
47
  debug('Login form successfully submitted.')
@@ -96,8 +66,10 @@ module.exports = async (pluginConfig, context) => {
96
66
  await page.waitForXPath(xpath, selectorOpts)
97
67
  debug('XPath found.')
98
68
  let nav = page.waitForNavigation(navOpts)
69
+ /* istanbul ignore next */
99
70
  const elements = await page.$x(xpath)
100
71
  debug('Delete Button - click.')
72
+ await elements[0].hover()
101
73
  await elements[0].click()
102
74
  debug('Delete Button - clicked.')
103
75
  await nav
@@ -108,6 +80,7 @@ module.exports = async (pluginConfig, context) => {
108
80
  await page.waitForSelector(selector, selectorOpts)
109
81
  debug('confirmation form loaded at %s', url)
110
82
  nav = page.waitForNavigation(navOpts)
83
+ await page.hover(selector)
111
84
  await page.click(selector)
112
85
  await nav
113
86
 
@@ -121,9 +94,7 @@ module.exports = async (pluginConfig, context) => {
121
94
  }
122
95
  }
123
96
 
124
- if (!DEBUG) {
125
- await browser.close()
126
- }
97
+ await page.browser().close()
127
98
  if (!success) {
128
99
  return false
129
100
  }
package/lib/get-error.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const SemanticReleaseError = require('@semantic-release/error')
2
2
  const ERROR_DEFINITIONS = require('./definitions/errors.js')
3
3
 
4
- module.exports = code => {
4
+ module.exports = (code) => {
5
5
  const { message, details } = ERROR_DEFINITIONS[code]()
6
6
  return new SemanticReleaseError(message, code, details)
7
7
  }
@@ -14,20 +14,22 @@ module.exports = async (pluginConfig, context) => {
14
14
  } = context
15
15
 
16
16
  debug('Getting releases from GitHub')
17
- logger.info('Getting releases from GitHub')
17
+ logger.log('Getting releases from GitHub')
18
18
 
19
19
  const { githubREPO, githubTOKEN } = resolveConfig(context)
20
20
 
21
21
  const gh = new GitHub({
22
22
  token: githubTOKEN
23
23
  })
24
- const repo = githubREPO.split('/')
25
- const githubReleases = await gh.getRepo(repo[0], repo[1]).listReleases()
26
- if (githubReleases.status === 200) {
27
- githubReleases.data.forEach(r => logger.log(`Detected GitHub release ${r.name.substring(1)}`))
28
- githubReleases.data.reverse()
29
- return githubReleases.data
24
+ if (githubREPO) { // optional by default false
25
+ const repo = githubREPO.split('/')
26
+ const githubReleases = await gh.getRepo(repo[0], repo[1]).listReleases()
27
+ if (githubReleases.status === 200) {
28
+ githubReleases.data.forEach(r => logger.log(`Detected GitHub release ${r.name.substring(1)}`))
29
+ githubReleases.data.reverse()
30
+ return githubReleases.data
31
+ }
32
+ logger.log('Failed to get releases from GitHub')
30
33
  }
31
- logger.error('Failed to get releases from GitHub')
32
34
  return false
33
35
  }
package/lib/publish.js CHANGED
@@ -1,13 +1,7 @@
1
- const debug = require('debug')('semantic-release:whmcs')
2
- const resolveConfig = require('./resolve-config')
3
- const puppeteer = require('puppeteer')
4
- const gotoOpts = {
5
- waitUntil: ['load', 'domcontentloaded'],
6
- timeout: 240000
7
- }
8
- const navOpts = { waitUntil: 'networkidle0', timeout: 240000 }
9
- const selectorOpts = { timeout: 240000 }
10
- const setCompatibleVersions = require('./set-compatible-versions')
1
+ const debug = require("debug")("semantic-release:whmcs");
2
+ const resolveConfig = require("./resolve-config");
3
+ const puppet = require("./puppet");
4
+ const setCompatibleVersions = require("./set-compatible-versions");
11
5
 
12
6
  /**
13
7
  * A method to publish the module update on whmcs market place
@@ -15,129 +9,127 @@ const setCompatibleVersions = require('./set-compatible-versions')
15
9
  module.exports = async (pluginConfig, context) => {
16
10
  const {
17
11
  nextRelease: { notes, version, releaseDate },
18
- logger
19
- } = context
12
+ logger,
13
+ } = context;
20
14
 
21
15
  if (!notes || !notes.length || !version || !version.length) {
22
- debug('publishing new product version failed. No input data available.')
23
- logger.error('WHMCS Marketplace publishing new product version failed. No input data available.')
16
+ debug("publishing new product version failed. No input data available.");
17
+ logger.error(
18
+ "WHMCS Marketplace publishing new product version failed. No input data available."
19
+ );
24
20
  }
25
21
 
26
- let success = true
27
- const { whmcsLOGIN, whmcsPASSWORD, whmcsPRODUCTID, DEBUG } = resolveConfig(context)
22
+ let success = true;
23
+ const { whmcsLOGIN, whmcsPASSWORD, whmcsPRODUCTID, DEBUG } =
24
+ resolveConfig(context);
25
+ const { gotoOpts, navOpts, selectorOpts, page } = await puppet(DEBUG, logger);
28
26
 
29
- debug(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`)
30
- logger.log(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`)
27
+ debug(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`);
28
+ logger.log(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`);
31
29
 
32
- debug(`Release Version: ${version}`)
33
- logger.log(`Release Version: ${version}`)
34
- debug(`Notes: ${notes}`)
35
- logger.log(`Release Notes: ${notes}`)
30
+ debug(`Release Version: ${version}`);
31
+ logger.log(`Release Version: ${version}`);
32
+ debug(`Notes: ${notes}`);
33
+ logger.log(`Release Notes: ${notes}`);
36
34
 
37
35
  // strip markdown links from notes as not allowed to keep
38
- const cleanedNotes = notes.replace(/\[(.*?)\]\((.+?)\)/gm, '$1')
39
- const wmbase = 'https://marketplace.whmcs.com'
40
- let url = `${wmbase}/user/login`
41
- const browser = await puppeteer.launch({
42
- headless: !DEBUG,
43
- defaultViewport: null, // automatically full-sized
44
- args: [
45
- '--incognito',
46
- '--start-maximized',
47
- '--no-sandbox',
48
- '--disable-setuid-sandbox',
49
- '--disable-infobars',
50
- '--ignore-certifcate-errors',
51
- '--ignore-certifcate-errors-spki-list',
52
- '--ignoreHTTPSErrors=true',
53
- '--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"'
54
- ]
55
- })
56
- const [page] = await browser.pages()
36
+ const cleanedNotes = notes.replace(/\[([^\]]*?)\]\(([^)]+?)\)/gm, "$1");
37
+ const wmbase = "https://marketplace.whmcs.com";
38
+ let url = `${wmbase}/user/login`;
57
39
 
58
40
  try {
59
- await page.setRequestInterception(true)
60
- page.on('request', request => {
61
- if (/^(image|stylesheet|other)$/i.test(request.resourceType())) {
62
- request.abort()
63
- } else {
64
- request.continue()
65
- }
66
- })
67
-
68
- await page.setJavaScriptEnabled(true)
69
- await page.goto(url, gotoOpts)
41
+ await page.goto(url, gotoOpts);
70
42
  // do login
71
- const selector = 'div.login-leftcol form button[type="submit"]'
72
- await page.waitForSelector(selector, selectorOpts)
73
- debug('login form loaded at %s', url)
74
- await page.type('#email', whmcsLOGIN)
75
- await page.type('#password', whmcsPASSWORD)
76
- debug('WHMCS Marketplace credentials entered')
77
- const nav = page.waitForNavigation(navOpts)
78
- await page.click(selector)
79
- await nav
80
- debug('Login form successfully submitted.')
81
- logger.log('WHMCS Marketplace Login Form successfully submitted.')
43
+ const selector = 'div.login-leftcol form button[type="submit"]';
44
+ await page.waitForSelector(selector, selectorOpts);
45
+ debug("login form loaded at %s", url);
46
+ await page.type("#email", whmcsLOGIN);
47
+ await page.type("#password", whmcsPASSWORD);
48
+ debug("WHMCS Marketplace credentials entered");
49
+ const nav = page.waitForNavigation(navOpts);
50
+ await page.hover(selector);
51
+ await page.click(selector);
52
+ await nav;
53
+ debug("Login form successfully submitted.");
54
+ logger.log("WHMCS Marketplace Login Form successfully submitted.");
82
55
  } catch (error) {
83
- debug('WHMCS Marketplace login failed.', error.message)
84
- logger.error('WHMCS Marketplace login failed.', error.message)
85
- success = false
56
+ debug("WHMCS Marketplace login failed.", error.message);
57
+ logger.error("WHMCS Marketplace login failed.", error.message);
58
+ success = false;
86
59
  }
87
60
  if (success) {
88
61
  try {
89
62
  if (!parseInt(whmcsPRODUCTID, 10)) {
90
- return false
63
+ return false;
91
64
  }
92
65
  // add new version
93
- url = `${wmbase}/product/${whmcsPRODUCTID}/versions/new`
94
- await page.goto(url, gotoOpts)
95
- debug('product page loaded at %s', url)
96
- const selector = 'div.listing-edit-container form button[type="submit"]'
97
- await page.waitForSelector(selector, selectorOpts)
98
- debug('product page submit button selector found')
99
- await page.$eval('#version', (el, value) => {
100
- el.value = value
101
- }, version)
102
- debug('form input for version finished.')
66
+ url = `${wmbase}/product/${whmcsPRODUCTID}/versions/new`;
67
+ await page.goto(url, gotoOpts);
68
+ debug("product page loaded at %s", url);
69
+ const selector = 'div.listing-edit-container form button[type="submit"]';
70
+ await page.waitForSelector(selector, selectorOpts);
71
+ debug("product page submit button selector found");
72
+ /* istanbul ignore next */
73
+ await page.$eval(
74
+ "#version",
75
+ (el, value) => {
76
+ el.value = value;
77
+ },
78
+ version
79
+ );
80
+ debug("form input for version finished.");
103
81
 
104
82
  // fill input type date with localized string
105
83
  // https://www.mattzeunert.com/2020/04/01/filling-out-a-date-input-with-puppeteer.html
106
- const date = releaseDate ? new Date(releaseDate) : new Date()
107
- const dateString = await page.evaluate(d => new Date(d).toLocaleDateString(navigator.language, {
108
- day: '2-digit',
109
- month: '2-digit',
110
- year: 'numeric'
111
- }), date.toISOString())
112
- await page.type('#released_at', dateString)
84
+ const date = releaseDate ? new Date(releaseDate) : new Date();
85
+ /* istanbul ignore next */
86
+ const dateString = await page.evaluate(
87
+ (d) =>
88
+ new Date(d).toLocaleDateString(navigator.language, {
89
+ day: "2-digit",
90
+ month: "2-digit",
91
+ year: "numeric",
92
+ }),
93
+ date.toISOString()
94
+ );
95
+ await page.type("#released_at", dateString);
113
96
 
114
- debug('form input for released_at finished.')
115
- await page.$eval('#description', (el, value) => {
116
- el.value = value
117
- }, cleanedNotes)
118
- debug('form input for description finished.')
119
- const nav = page.waitForNavigation(navOpts)
120
- await page.click(selector)
121
- await nav
97
+ debug("form input for released_at finished.");
98
+ /* istanbul ignore next */
99
+ await page.$eval(
100
+ "#description",
101
+ (el, value) => {
102
+ el.value = value;
103
+ },
104
+ cleanedNotes
105
+ );
106
+ debug("form input for description finished.");
107
+ const nav = page.waitForNavigation(navOpts);
108
+ await page.hover(selector);
109
+ await page.click(selector);
110
+ await nav;
122
111
 
123
- await setCompatibleVersions(pluginConfig, context)
112
+ await setCompatibleVersions(pluginConfig, context);
124
113
 
125
- debug('publishing new product version succeeded.')
126
- logger.log('WHMCS Marketplace publishing new product version succeeded.')
127
- success = true
114
+ debug("publishing new product version succeeded.");
115
+ logger.log("WHMCS Marketplace publishing new product version succeeded.");
116
+ success = true;
128
117
  } catch (error) {
129
- debug('publishing new product version failed.', error.message)
130
- logger.error('WHMCS Marketplace publishing new product version failed.', error.message)
131
- success = false
118
+ debug("publishing new product version failed.", error.message);
119
+ logger.error(
120
+ "WHMCS Marketplace publishing new product version failed.",
121
+ error.message
122
+ );
123
+ success = false;
132
124
  }
133
125
  }
134
126
 
135
- await browser.close()
127
+ await page.browser().close();
136
128
  if (!success) {
137
- return false
129
+ return false;
138
130
  }
139
131
  return {
140
- name: 'WHMCS Marketplace Product Version',
141
- url: `${wmbase}/product/${whmcsPRODUCTID}`
142
- }
143
- }
132
+ name: "WHMCS Marketplace Product Version",
133
+ url: `${wmbase}/product/${whmcsPRODUCTID}`,
134
+ };
135
+ };