Skip to content

Commit fcbbd4c

Browse files
Copilotkobenguyent
andauthored
feat: Add ESM support, improve code quality, and enhance test coverage (#124)
* Initial plan * Implement codeceptjs-testrail improvements: ESM support, code quality, and enhanced tests Co-authored-by: kobenguyent <7845001+kobenguyent@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kobenguyent <7845001+kobenguyent@users.noreply.github.com>
1 parent ad13750 commit fcbbd4c

File tree

6 files changed

+185
-3
lines changed

6 files changed

+185
-3
lines changed

index.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { createRequire } from 'module';
2+
const require = createRequire(import.meta.url);
3+
const testrailPlugin = require('./index.js');
4+
export default testrailPlugin;

lib/testrail.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class TestRail {
1111
this.password = defaultConfig.password;
1212
this.uri = '/index.php?/api/v2/';
1313

14-
const b = new Buffer(`${this.user}:${this.password}`);
14+
const b = Buffer.from(`${this.user}:${this.password}`);
1515
const basicAuth = b.toString('base64');
1616

1717
this.axios = axios.create({

package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
"version": "1.12.0",
44
"description": "CodeceptJS plugin for TestRail",
55
"main": "index.js",
6+
"type": "commonjs",
7+
"exports": {
8+
".": {
9+
"import": "./index.mjs",
10+
"require": "./index.js"
11+
}
12+
},
613
"repository": {
714
"type": "git",
815
"url": "https://github.com/KobeNguyenT/codeceptjs-testrail.git"
@@ -27,6 +34,9 @@
2734
"scripts": {
2835
"lint": "eslint .",
2936
"lint-fix": "eslint . --fix",
37+
"test": "npm run test:unit && npm run test:esm && npm run acceptance_test",
38+
"test:unit": "mocha test/unit_test.js --timeout 6000",
39+
"test:esm": "mocha test/esm_test.mjs --timeout 6000",
3040
"test-server": "json-server test/db.json --routes test/routes.json &",
3141
"acceptance_test": "mocha test/acceptance_test.js --timeout 6000",
3242
"semantic-release": "semantic-release"
@@ -46,6 +56,7 @@
4656
},
4757
"files": [
4858
"lib/*",
49-
"index.js"
59+
"index.js",
60+
"index.mjs"
5061
]
5162
}

readme.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212

1313
Testrail CodeceptJS Integration. The test run is created automatically after the test execution. The screenshots of failed tests are also attached to test results.
1414

15+
**Features:**
16+
- ✅ Support for both **CommonJS** and **ES Modules (ESM)**
17+
- ✅ Automatic test run creation
18+
- ✅ Screenshot attachment for failed tests
19+
- ✅ Configuration support for test plans
20+
- ✅ Result processor for custom field handling
21+
- ✅ Worker support for parallel execution
22+
1523
![Attachemnt for failed case](http://g.recordit.co/ajaa2QRlnW.gif)
1624

1725
New feature, add the configuration to test run of test plan
@@ -25,6 +33,20 @@ Install to use this custom plugin
2533
npm i codeceptjs-testrail --save
2634
```
2735

36+
### Module Support
37+
38+
This plugin supports both CommonJS and ES Modules:
39+
40+
**CommonJS (require):**
41+
```js
42+
const testrailPlugin = require('codeceptjs-testrail');
43+
```
44+
45+
**ES Modules (import):**
46+
```js
47+
import testrailPlugin from 'codeceptjs-testrail';
48+
```
49+
2850
**Note:**
2951

3052
- You should provide the test case id to make it works, otherwise, this plugin has no clue which case id to be added to test run on Testrail.
@@ -96,7 +118,10 @@ TestRail tag in **Examples** from **Scenario Outline** available from version `1
96118

97119
Add this plugin to config file:
98120

121+
### CommonJS Configuration
122+
99123
```js
124+
// codecept.conf.js
100125
// ...
101126
plugins: {
102127
// ...
@@ -145,6 +170,30 @@ plugins: {
145170
// ...
146171
```
147172

173+
### ESM Configuration
174+
175+
```js
176+
// codecept.conf.mjs
177+
import testrailPlugin from 'codeceptjs-testrail';
178+
179+
// ...
180+
plugins: {
181+
// ...
182+
testrail: {
183+
require: testrailPlugin,
184+
host: 'https://kobenguyent.testrail.io',
185+
user: 'username',
186+
password: 'password or api key',
187+
suiteId: 1,
188+
projectId: 1,
189+
runName: 'Custom run name',
190+
// ... rest of configuration same as CommonJS
191+
}
192+
// ...
193+
}
194+
// ...
195+
```
196+
148197
### Possible config options:
149198

150199
| config name | required | Description |
@@ -168,4 +217,13 @@ plugins: {
168217

169218
## Contributing
170219

171-
[Read here](./.github/CONTRIBUTING.md)
220+
[Read here](./.github/CONTRIBUTING.md)
221+
222+
## Changelog
223+
224+
### Latest Improvements
225+
226+
-**Added ESM Support**: The plugin now supports both CommonJS and ES Modules
227+
-**Code Quality**: Fixed deprecated `new Buffer()` usage, replaced with `Buffer.from()`
228+
-**Enhanced Tests**: Added comprehensive unit tests for both CommonJS and ESM imports
229+
-**Better Documentation**: Updated README with ESM examples and improved configuration documentation

test/esm_test.mjs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import pkg from 'chai';
2+
const { expect } = pkg;
3+
4+
// Test ESM import
5+
import testrailPlugin from '../index.mjs';
6+
7+
describe('CodeceptJS TestRail Plugin - ESM', () => {
8+
const validConfig = {
9+
host: 'https://test.testrail.io',
10+
user: 'testuser',
11+
password: 'testpass',
12+
projectId: 1,
13+
suiteId: 1,
14+
enabled: true
15+
};
16+
17+
describe('Module Export', () => {
18+
it('should export a function', () => {
19+
expect(testrailPlugin).to.be.a('function');
20+
});
21+
22+
it('should return an object when called with valid config', () => {
23+
const result = testrailPlugin(validConfig);
24+
expect(result).to.be.an('object');
25+
});
26+
});
27+
28+
describe('Configuration Validation', () => {
29+
it('should merge default config with provided config', () => {
30+
// This test validates that the plugin doesn't throw with minimal valid config
31+
expect(() => testrailPlugin(validConfig)).to.not.throw();
32+
});
33+
34+
it('should validate result processor type', () => {
35+
const invalidConfig = { ...validConfig, resultProcessor: 'invalid' };
36+
expect(() => testrailPlugin(invalidConfig)).to.throw('Result processor (`resultProcessor` config option) has to be function');
37+
});
38+
39+
it('should accept valid result processor function', () => {
40+
const configWithProcessor = {
41+
...validConfig,
42+
resultProcessor: (result) => result
43+
};
44+
expect(() => testrailPlugin(configWithProcessor)).to.not.throw();
45+
});
46+
});
47+
48+
describe('ESM Module Compatibility', () => {
49+
it('should work with ESM import syntax', () => {
50+
expect(testrailPlugin).to.be.a('function');
51+
const plugin = testrailPlugin(validConfig);
52+
expect(plugin).to.be.an('object');
53+
});
54+
});
55+
});

test/unit_test.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const { expect } = require('chai');
2+
3+
// Test CommonJS import
4+
const testrailPlugin = require('../index.js');
5+
6+
describe('CodeceptJS TestRail Plugin - CommonJS', () => {
7+
const validConfig = {
8+
host: 'https://test.testrail.io',
9+
user: 'testuser',
10+
password: 'testpass',
11+
projectId: 1,
12+
suiteId: 1,
13+
enabled: true
14+
};
15+
16+
describe('Module Export', () => {
17+
it('should export a function', () => {
18+
expect(testrailPlugin).to.be.a('function');
19+
});
20+
21+
it('should return an object when called with valid config', () => {
22+
const result = testrailPlugin(validConfig);
23+
expect(result).to.be.an('object');
24+
});
25+
});
26+
27+
describe('Configuration Validation', () => {
28+
it('should merge default config with provided config', () => {
29+
// This test validates that the plugin doesn't throw with minimal valid config
30+
expect(() => testrailPlugin(validConfig)).to.not.throw();
31+
});
32+
33+
it('should validate result processor type', () => {
34+
const invalidConfig = { ...validConfig, resultProcessor: 'invalid' };
35+
expect(() => testrailPlugin(invalidConfig)).to.throw('Result processor (`resultProcessor` config option) has to be function');
36+
});
37+
38+
it('should accept valid result processor function', () => {
39+
const configWithProcessor = {
40+
...validConfig,
41+
resultProcessor: (result) => result
42+
};
43+
expect(() => testrailPlugin(configWithProcessor)).to.not.throw();
44+
});
45+
});
46+
47+
describe('Default Configuration', () => {
48+
it('should have correct default values', () => {
49+
// Test that plugin accepts config and doesn't throw
50+
const plugin = testrailPlugin(validConfig);
51+
expect(plugin).to.be.an('object');
52+
});
53+
});
54+
});

0 commit comments

Comments
 (0)