Skip to content

Commit 6ed1f82

Browse files
author
David Haeffner
committed
Added plugin support for adding new languages to code export. Supports
PR #734
1 parent 75b941b commit 6ed1f82

File tree

4 files changed

+77
-20
lines changed

4 files changed

+77
-20
lines changed

docs/plugins/code-export.md

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,39 @@ title: Code Export Plugin Support
44
sidebar_label: Exporting Code
55
---
66

7-
The plugins API enables any Selenium IDE plugin to be export code in response to certain events (or "hooks").
7+
The plugins API enables any Selenium IDE plugin to export code for either:
8+
9+
1. an existing language
10+
2. a new language
811

912
### Export config
1013

11-
In your plugin manifest you'll need to specify that it exports languages, and for which ones.
14+
In your plugin manifest you'll need to specify that it exports languages.
15+
16+
<u>Add to an existing language</u>
17+
18+
To augment an existing language, use the `languages` key and specify which ones in an array.
1219

1320
```javascript
1421
"exports": {
1522
"languages": ["java-junit"]
1623
}
1724
```
1825

26+
The currently available language ids `"java-junit"`, `"javascript-mocha"`, and `"python-pytest"`.
27+
28+
<u>Add a new language</u>
29+
30+
To add a new language to code export, use the `vendor` key and specify your langauge in an object array.
31+
32+
```javascript
33+
"exports": {
34+
"vendor": [{"your-language": "Your language"}]
35+
}
36+
```
37+
38+
The key is the ID which will be used in the export event. The value is the display name that will be used in the code export menu in the UI.
39+
1940
### Export event
2041

2142
Selenium IDE sends the following event for each entity type, which your plugin can respond to for code export.
@@ -30,7 +51,7 @@ Selenium IDE sends the following event for each entity type, which your plugin c
3051
```
3152

3253
- `action` - `export`, indicating an action that requires code export
33-
- `entity`, the entity to export, can be `command` or any of [the hooks mentioned in the next section](code-export.md#hooks)
54+
- `entity`, the entity to export, can be `command`, any of [the hooks mentioned in the next section](code-export.md#hooks), or `vendor` if exporting a new language
3455
- `options` - metadata to help your plugin make more informed decisions about what to export (e.g., project, test name, suite name, etc.)
3556

3657
## Hooks
@@ -49,6 +70,8 @@ Code export is built around the notion of hooks, which offers entry points into
4970

5071
## Response
5172

73+
### Add to an existing language
74+
5275
To respond to an export event, call `sendResponse` along with the string you'd like to export. If there are multiple lines to your string, separate them with newline characters (e.g., `\n`).
5376

5477
Or you can look into using the command object structure mentioned in the [code export getting started](introduction/code-export.md#2-update-the-locators-and-commands).
@@ -57,4 +80,16 @@ Or you can look into using the command object structure mentioned in the [code e
5780
sendResponse(`const myLibrary = require("my-library");`);
5881
```
5982

83+
### Add a new language
84+
85+
In response to a `vendor` export event for your new language(s), your plugin needs to respond with the an object containing the keys `filename` and `body`.
86+
87+
```javascript
88+
const payload = {
89+
filename: 'test.js',
90+
body: '// your final exported code\n// goes here\n// etc.'
91+
}
92+
sendResponse(payload)
93+
```
94+
6095

packages/selenium-ide/src/neo/code-export/index.js

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ import ModalState from '../stores/view/ModalState'
2020
import exporter from 'code-export'
2121
import { downloadUniqueFile } from '../IO/filesystem'
2222
import { normalizeTestsInSuite } from '../IO/normalize'
23+
import PluginManager from '../../plugin/manager'
24+
import { availableLanguages as languages } from 'code-export'
25+
const vendorLanguages = PluginManager.plugins.vendorLanguages
26+
27+
export function availableLanguages() {
28+
return Object.keys(vendorLanguages).length
29+
? { ...languages, ...vendorLanguages }
30+
: languages
31+
}
2332

2433
export async function exportCodeToFile(
2534
selectedLanguages,
@@ -30,22 +39,26 @@ export async function exportCodeToFile(
3039
const { url, tests } = project
3140
for (const language of selectedLanguages) {
3241
let emittedCode
33-
if (test) {
34-
emittedCode = await exporter.emit.test(language, {
35-
url,
36-
test,
37-
tests,
38-
project,
39-
enableOriginTracing,
42+
let options = {
43+
url,
44+
tests,
45+
project,
46+
enableOriginTracing,
47+
}
48+
options.test = test ? test : undefined
49+
options.suite = suite ? normalizeTestsInSuite({ suite, tests }) : undefined
50+
if (vendorLanguages.hasOwnProperty(language)) {
51+
const result = await PluginManager.emitMessage({
52+
action: 'export',
53+
entity: 'vendor',
54+
language,
55+
options,
4056
})
57+
emittedCode = result[0].response
58+
} else if (test) {
59+
emittedCode = await exporter.emit.test(language, options)
4160
} else if (suite) {
42-
emittedCode = await exporter.emit.suite(language, {
43-
url,
44-
suite: normalizeTestsInSuite({ suite, tests }),
45-
tests,
46-
project,
47-
enableOriginTracing,
48-
})
61+
emittedCode = await exporter.emit.suite(language, options)
4962
}
5063
if (emittedCode) downloadUniqueFile(emittedCode.filename, emittedCode.body)
5164
}

packages/selenium-ide/src/neo/components/Dialogs/Export/index.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import Modal from '../../Modal'
2121
import DialogContainer from '../Dialog'
2222
import FlatButton from '../../FlatButton'
2323
import Checkbox from '../../Checkbox'
24-
import { availableLanguages } from 'code-export'
24+
import { availableLanguages } from '../../../code-export'
2525
import './style.css'
2626

2727
export default class ExportDialog extends React.Component {
@@ -112,9 +112,10 @@ class ExportList extends React.Component {
112112
this.props.selectLanguage(e.target.checked, language)
113113
}
114114
render() {
115+
const languages = availableLanguages()
115116
return (
116117
<ul className="languages">
117-
{Object.keys(availableLanguages)
118+
{Object.keys(languages)
118119
.sort()
119120
.map(language => (
120121
<li key={language} className="language">
@@ -126,7 +127,7 @@ class ExportList extends React.Component {
126127
onChange={this.handleChange.bind(this, language)}
127128
/>
128129
<label htmlFor={language}>
129-
{availableLanguages[language].displayName}
130+
{languages[language].displayName}
130131
</label>
131132
</li>
132133
))}

packages/selenium-ide/src/plugin/manager.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ function RunCommand(id, command, target, value, options) {
4343
class PluginManager {
4444
constructor() {
4545
this.plugins = []
46+
this.plugins.vendorLanguages = {}
4647
RegisterConfigurationHook(project => {
4748
return new Promise(res => {
4849
Promise.all(
@@ -82,6 +83,13 @@ class PluginManager {
8283
RegisterSuiteHook(this.emitSuite.bind(undefined, plugin))
8384
RegisterTestHook(this.emitTest.bind(undefined, plugin))
8485
if (plugin.exports) {
86+
if (plugin.exports.vendor) {
87+
plugin.exports.vendor.forEach(language => {
88+
const id = Object.keys(language)[0]
89+
const displayName = Object.values(language)[0]
90+
this.plugins.vendorLanguages[id] = { displayName }
91+
})
92+
}
8593
plugin.exports.languages.forEach(language => {
8694
Object.keys(exporter.register).forEach(register => {
8795
if (register !== 'command') {

0 commit comments

Comments
 (0)