@hexonet/semantic-release-whmcs 3.0.2 → 3.1.2

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 (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
+ };