@orangebeard-io/playwright-orangebeard-reporter 1.0.1 → 1.0.3
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.
- package/LICENSE +202 -661
- package/dist/reporter/OrangebeardReporter.js +283 -0
- package/dist/reporter/utils.js +177 -0
- package/package.json +4 -1
- package/.eslintignore +0 -5
- package/.eslintrc +0 -22
- package/.github/logo.svg +0 -66
- package/.github/workflows/release.yml +0 -144
- package/.prettierrc +0 -7
- package/changelog-template.hbs +0 -29
- package/src/index.ts +0 -3
- package/src/reporter/OrangebeardReporter.ts +0 -265
- package/src/reporter/utils.ts +0 -160
- package/tsconfig.json +0 -20
| @@ -1,144 +0,0 @@ | |
| 1 | 
            -
            name: release
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            on:
         | 
| 4 | 
            -
              push:
         | 
| 5 | 
            -
                branches:
         | 
| 6 | 
            -
                  - main
         | 
| 7 | 
            -
             | 
| 8 | 
            -
            jobs:
         | 
| 9 | 
            -
              get-version:
         | 
| 10 | 
            -
                runs-on: ubuntu-latest
         | 
| 11 | 
            -
                outputs:
         | 
| 12 | 
            -
                  releaseVersion: ${{ steps.exposeVersion.outputs.releaseVersion }}
         | 
| 13 | 
            -
                steps:
         | 
| 14 | 
            -
                  - name: Checkout repository
         | 
| 15 | 
            -
                    uses: actions/checkout@v4
         | 
| 16 | 
            -
                  - name: Setup Node.js
         | 
| 17 | 
            -
                    uses: actions/setup-node@v4
         | 
| 18 | 
            -
                    with:
         | 
| 19 | 
            -
                      node-version: '20'
         | 
| 20 | 
            -
                  - name: Cache node modules
         | 
| 21 | 
            -
                    uses: actions/cache@v4
         | 
| 22 | 
            -
                    with:
         | 
| 23 | 
            -
                      path: node_modules
         | 
| 24 | 
            -
                      key: node_modules-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
         | 
| 25 | 
            -
                      restore-keys: |
         | 
| 26 | 
            -
                        node_modules-
         | 
| 27 | 
            -
                  - name: Install Node dependencies
         | 
| 28 | 
            -
                    run: npm install
         | 
| 29 | 
            -
                  - name: Get version from package.json
         | 
| 30 | 
            -
                    id: exposeVersion
         | 
| 31 | 
            -
                    run: echo "releaseVersion=$(npm run get-version --silent)" >> $GITHUB_OUTPUT
         | 
| 32 | 
            -
              prepare-release:
         | 
| 33 | 
            -
                needs: get-version
         | 
| 34 | 
            -
                runs-on: ubuntu-latest
         | 
| 35 | 
            -
                outputs:
         | 
| 36 | 
            -
                  versionInfo: ${{ steps.readChangelogEntry.outputs.log_entry }}
         | 
| 37 | 
            -
                steps:
         | 
| 38 | 
            -
                  - name: Checkout repository
         | 
| 39 | 
            -
                    uses: actions/checkout@v4
         | 
| 40 | 
            -
                  - name: Configure git
         | 
| 41 | 
            -
                    run: |
         | 
| 42 | 
            -
                      git config --global user.email "info@orangebeard.io"
         | 
| 43 | 
            -
                      git config --global user.name "Orangebeard.io"
         | 
| 44 | 
            -
                  - name: Create tag
         | 
| 45 | 
            -
                    run: |
         | 
| 46 | 
            -
                      git tag -a v${{ needs.get-version.outputs.releaseVersion }} -m ${{ needs.get-version.outputs.releaseVersion }}
         | 
| 47 | 
            -
                      git push origin main --follow-tags
         | 
| 48 | 
            -
                  - name: Setup Node.js
         | 
| 49 | 
            -
                    uses: actions/setup-node@v4
         | 
| 50 | 
            -
                    with:
         | 
| 51 | 
            -
                      node-version: '20'
         | 
| 52 | 
            -
                  - name: Cache node modules
         | 
| 53 | 
            -
                    uses: actions/cache@v4
         | 
| 54 | 
            -
                    with:
         | 
| 55 | 
            -
                      path: node_modules
         | 
| 56 | 
            -
                      key: node_modules-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
         | 
| 57 | 
            -
                      restore-keys: |
         | 
| 58 | 
            -
                        node_modules-
         | 
| 59 | 
            -
                  - name: Install Node dependencies
         | 
| 60 | 
            -
                    run: npm install
         | 
| 61 | 
            -
                  - name: Create CHANGELOG.md
         | 
| 62 | 
            -
                    run: npm run create-changelog
         | 
| 63 | 
            -
                  - name: Upload changelog as artifact
         | 
| 64 | 
            -
                    uses: actions/upload-artifact@v4
         | 
| 65 | 
            -
                    with:
         | 
| 66 | 
            -
                      name: changelog
         | 
| 67 | 
            -
                      path: CHANGELOG.md
         | 
| 68 | 
            -
              create-release:
         | 
| 69 | 
            -
                needs: [get-version, prepare-release]
         | 
| 70 | 
            -
                runs-on: ubuntu-latest
         | 
| 71 | 
            -
                steps:
         | 
| 72 | 
            -
                  - name: Checkout repository
         | 
| 73 | 
            -
                    uses: actions/checkout@v4
         | 
| 74 | 
            -
                  - name: Download changelog for artifact
         | 
| 75 | 
            -
                    uses: actions/download-artifact@v4
         | 
| 76 | 
            -
                    with:
         | 
| 77 | 
            -
                      name: changelog
         | 
| 78 | 
            -
                  - name: Create Release
         | 
| 79 | 
            -
                    id: createRelease
         | 
| 80 | 
            -
                    uses: ncipollo/release-action@v1
         | 
| 81 | 
            -
                    env:
         | 
| 82 | 
            -
                      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         | 
| 83 | 
            -
                    with:
         | 
| 84 | 
            -
                      tag: v${{ needs.get-version.outputs.releaseVersion }}
         | 
| 85 | 
            -
                      name: ${{ needs.get-version.outputs.releaseVersion }}
         | 
| 86 | 
            -
                      bodyFile: CHANGELOG.md
         | 
| 87 | 
            -
              publish-release:
         | 
| 88 | 
            -
                needs: [get-version, prepare-release, create-release]
         | 
| 89 | 
            -
                runs-on: ubuntu-latest
         | 
| 90 | 
            -
                permissions:
         | 
| 91 | 
            -
                  contents: read
         | 
| 92 | 
            -
                  id-token: write
         | 
| 93 | 
            -
                steps:
         | 
| 94 | 
            -
                  - name: Checkout repository
         | 
| 95 | 
            -
                    uses: actions/checkout@v4
         | 
| 96 | 
            -
                  - name: Setup Node.js
         | 
| 97 | 
            -
                    uses: actions/setup-node@v4
         | 
| 98 | 
            -
                    with:
         | 
| 99 | 
            -
                      node-version: '20'
         | 
| 100 | 
            -
                      registry-url: 'https://registry.npmjs.org'
         | 
| 101 | 
            -
                  - name: Cache node modules
         | 
| 102 | 
            -
                    uses: actions/cache@v4
         | 
| 103 | 
            -
                    with:
         | 
| 104 | 
            -
                      path: node_modules
         | 
| 105 | 
            -
                      key: node_modules-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
         | 
| 106 | 
            -
                      restore-keys: |
         | 
| 107 | 
            -
                        node_modules-
         | 
| 108 | 
            -
                  - name: Transpile to JS
         | 
| 109 | 
            -
                    run: npm run build
         | 
| 110 | 
            -
                  - name: Install Node dependencies
         | 
| 111 | 
            -
                    run: npm install
         | 
| 112 | 
            -
                  - name: Publish to NPM
         | 
| 113 | 
            -
                    run: npm publish --provenance --access public
         | 
| 114 | 
            -
                    env:
         | 
| 115 | 
            -
                      NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
         | 
| 116 | 
            -
              update-version:
         | 
| 117 | 
            -
                needs: [get-version, prepare-release, create-release, publish-release]
         | 
| 118 | 
            -
                runs-on: ubuntu-latest
         | 
| 119 | 
            -
                steps:
         | 
| 120 | 
            -
                  - name: Checkout repository
         | 
| 121 | 
            -
                    uses: actions/checkout@v4
         | 
| 122 | 
            -
                  - name: Configure git
         | 
| 123 | 
            -
                    run: |
         | 
| 124 | 
            -
                      git config --global user.email "info@orangebeard.io"
         | 
| 125 | 
            -
                      git config --global user.name "Orangebeard.io"
         | 
| 126 | 
            -
                  - name: Setup Node.js
         | 
| 127 | 
            -
                    uses: actions/setup-node@v4
         | 
| 128 | 
            -
                    with:
         | 
| 129 | 
            -
                      node-version: '20'
         | 
| 130 | 
            -
                  - name: Cache node modules
         | 
| 131 | 
            -
                    uses: actions/cache@v4
         | 
| 132 | 
            -
                    with:
         | 
| 133 | 
            -
                      path: node_modules
         | 
| 134 | 
            -
                      key: node_modules-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
         | 
| 135 | 
            -
                      restore-keys: |
         | 
| 136 | 
            -
                        node_modules-
         | 
| 137 | 
            -
                  - name: Install Node dependencies
         | 
| 138 | 
            -
                    run: npm install
         | 
| 139 | 
            -
                  - name: Update version
         | 
| 140 | 
            -
                    run: |
         | 
| 141 | 
            -
                      npm run update-version
         | 
| 142 | 
            -
                      git add package.json package-lock.json
         | 
| 143 | 
            -
                      git commit -m "Update version"
         | 
| 144 | 
            -
                      git push origin main
         | 
    
        package/.prettierrc
    DELETED
    
    
    
        package/changelog-template.hbs
    DELETED
    
    | @@ -1,29 +0,0 @@ | |
| 1 | 
            -
            {{#each releases}}
         | 
| 2 | 
            -
              {{#if summary}}
         | 
| 3 | 
            -
                {{summary}}
         | 
| 4 | 
            -
              {{/if}}
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              {{#if merges}}
         | 
| 7 | 
            -
                ### :twisted_rightwards_arrows: Merged
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                {{#each merges}}
         | 
| 10 | 
            -
                  - {{#if commit.breaking}}**Breaking change:** {{/if}}{{message}} {{#if href}}[`#{{id}}`]({{href}}){{/if}}
         | 
| 11 | 
            -
                {{/each}}
         | 
| 12 | 
            -
              {{/if}}
         | 
| 13 | 
            -
             | 
| 14 | 
            -
              {{#if fixes}}
         | 
| 15 | 
            -
                ### :bug: Fixed
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                {{#each fixes}}
         | 
| 18 | 
            -
                  - {{#if commit.breaking}}**Breaking change:** {{/if}}{{commit.subject}}{{#each fixes}} {{#if href}}[`#{{id}}`]({{href}}){{/if}}{{/each}}
         | 
| 19 | 
            -
                {{/each}}
         | 
| 20 | 
            -
              {{/if}}
         | 
| 21 | 
            -
             | 
| 22 | 
            -
              {{#commit-list commits heading='### :mag: Commits'}}
         | 
| 23 | 
            -
                - {{#if breaking}}**Breaking change:** {{/if}}{{subject}} {{#if href}}[`{{shorthash}}`]({{href}}){{/if}}
         | 
| 24 | 
            -
              {{/commit-list}}
         | 
| 25 | 
            -
             | 
| 26 | 
            -
              {{#if href}}
         | 
| 27 | 
            -
                See full comparison at [{{title}}]({{href}})
         | 
| 28 | 
            -
              {{/if}}
         | 
| 29 | 
            -
            {{/each}}
         | 
    
        package/src/index.ts
    DELETED
    
    
| @@ -1,265 +0,0 @@ | |
| 1 | 
            -
            import {UUID} from 'crypto';
         | 
| 2 | 
            -
            import {Reporter, TestCase, TestResult, TestStep} from '@playwright/test/reporter'
         | 
| 3 | 
            -
            import {ansiToMarkdown, getBytes, getCodeSnippet, getTime, removeAnsi, testStatusMap} from './utils'
         | 
| 4 | 
            -
            import {OrangebeardParameters} from "@orangebeard-io/javascript-client/dist/client/models/OrangebeardParameters";
         | 
| 5 | 
            -
            import OrangebeardAsyncV3Client from "@orangebeard-io/javascript-client/dist/client/OrangebeardAsyncV3Client";
         | 
| 6 | 
            -
            import {StartTest} from "@orangebeard-io/javascript-client/dist/client/models/StartTest";
         | 
| 7 | 
            -
            import {Attachment} from "@orangebeard-io/javascript-client/dist/client/models/Attachment";
         | 
| 8 | 
            -
            import {Log} from "@orangebeard-io/javascript-client/dist/client/models/Log";
         | 
| 9 | 
            -
            import {Attribute} from "@orangebeard-io/javascript-client/dist/client/models/Attribute";
         | 
| 10 | 
            -
            import {FinishStep} from "@orangebeard-io/javascript-client/dist/client/models/FinishStep";
         | 
| 11 | 
            -
            import TestType = StartTest.TestType;
         | 
| 12 | 
            -
            import LogFormat = Log.LogFormat;
         | 
| 13 | 
            -
            import LogLevel = Log.LogLevel;
         | 
| 14 | 
            -
            import Status = FinishStep.Status;
         | 
| 15 | 
            -
            import * as path from "node:path";
         | 
| 16 | 
            -
             | 
| 17 | 
            -
            export class OrangebeardReporter implements Reporter {
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                config: OrangebeardParameters;
         | 
| 20 | 
            -
                client: OrangebeardAsyncV3Client;
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                //CONTEXT TRACKING
         | 
| 23 | 
            -
                testRunId: UUID;
         | 
| 24 | 
            -
                suites: Map<string, UUID> = new Map<string, UUID>(); //suiteNames , uuid
         | 
| 25 | 
            -
                tests: Map<string, UUID> = new Map<string, UUID>(); //testId, uuid
         | 
| 26 | 
            -
                steps: Map<string, UUID> = new Map<string, UUID>(); //testId_stepPath, uuid
         | 
| 27 | 
            -
                promises: Promise<void>[] = [];
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                constructor() {
         | 
| 30 | 
            -
                    this.client = new OrangebeardAsyncV3Client();
         | 
| 31 | 
            -
                    this.config = this.client.config;
         | 
| 32 | 
            -
                }
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                onBegin(): void {
         | 
| 35 | 
            -
                    this.testRunId = this.client.startTestRun({
         | 
| 36 | 
            -
                        testSetName: this.config.testset,
         | 
| 37 | 
            -
                        description: this.config.description,
         | 
| 38 | 
            -
                        startTime: getTime(),
         | 
| 39 | 
            -
                        attributes: this.config.attributes
         | 
| 40 | 
            -
                    })
         | 
| 41 | 
            -
                }
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                async onEnd(): Promise<void> {
         | 
| 44 | 
            -
                    await Promise.all(this.promises)
         | 
| 45 | 
            -
                    return this.client.finishTestRun(this.testRunId, {endTime: getTime()})
         | 
| 46 | 
            -
                }
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                onStdErr(chunk: string | Buffer, test: void | TestCase, _result: void | TestResult): void {
         | 
| 49 | 
            -
                    //log error level
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                    if (typeof test === 'object' && test !== null) {
         | 
| 52 | 
            -
                        const testUUID = this.tests.get(test.id);
         | 
| 53 | 
            -
                        const message = chunk.toString();
         | 
| 54 | 
            -
                        this.client.log({
         | 
| 55 | 
            -
                            logFormat: LogFormat.PLAIN_TEXT,
         | 
| 56 | 
            -
                            logLevel: LogLevel.ERROR,
         | 
| 57 | 
            -
                            logTime: getTime(),
         | 
| 58 | 
            -
                            message: message,
         | 
| 59 | 
            -
                            testRunUUID: this.testRunId,
         | 
| 60 | 
            -
                            testUUID: testUUID
         | 
| 61 | 
            -
                        });
         | 
| 62 | 
            -
                    }
         | 
| 63 | 
            -
                }
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                onStdOut(chunk: string | Buffer, test: void | TestCase, _result: void | TestResult): void {
         | 
| 66 | 
            -
                    if (typeof test === 'object' && test !== null) {
         | 
| 67 | 
            -
                        const testUUID = this.tests.get(test.id);
         | 
| 68 | 
            -
                        const message = chunk.toString();
         | 
| 69 | 
            -
                        this.client.log({
         | 
| 70 | 
            -
                            logFormat: LogFormat.PLAIN_TEXT,
         | 
| 71 | 
            -
                            logLevel: LogLevel.INFO,
         | 
| 72 | 
            -
                            logTime: getTime(),
         | 
| 73 | 
            -
                            message: message,
         | 
| 74 | 
            -
                            testRunUUID: this.testRunId,
         | 
| 75 | 
            -
                            testUUID: testUUID
         | 
| 76 | 
            -
                        });
         | 
| 77 | 
            -
                    }
         | 
| 78 | 
            -
                }
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                onStepBegin(test: TestCase, _result: TestResult, step: TestStep): void {
         | 
| 81 | 
            -
                    //start step
         | 
| 82 | 
            -
                    const testUUID = this.tests.get(test.id);
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                    const stepUUID = this.client.startStep({
         | 
| 85 | 
            -
                        startTime: getTime(),
         | 
| 86 | 
            -
                        stepName: step.title,
         | 
| 87 | 
            -
                        description: step.location ? `${path.basename(step.location.file)}:${step.location.line}`: undefined,
         | 
| 88 | 
            -
                        testRunUUID: this.testRunId,
         | 
| 89 | 
            -
                        testUUID: testUUID,
         | 
| 90 | 
            -
                        parentStepUUID: step.parent ? this.steps.get(test.id + "|" + step.parent.titlePath()) : undefined,
         | 
| 91 | 
            -
                    })
         | 
| 92 | 
            -
                    this.steps.set(test.id + "|" + step.titlePath(), stepUUID)
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                    if(step.location) {
         | 
| 95 | 
            -
                        this.client.log({
         | 
| 96 | 
            -
                            logFormat: LogFormat.MARKDOWN,
         | 
| 97 | 
            -
                            logLevel: LogLevel.INFO,
         | 
| 98 | 
            -
                            logTime: getTime(),
         | 
| 99 | 
            -
                            message: getCodeSnippet(step.location.file, step.location.line),
         | 
| 100 | 
            -
                            testRunUUID: this.testRunId,
         | 
| 101 | 
            -
                            testUUID: testUUID,
         | 
| 102 | 
            -
                            stepUUID: stepUUID
         | 
| 103 | 
            -
                        });
         | 
| 104 | 
            -
                    }
         | 
| 105 | 
            -
                }
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                onStepEnd(test: TestCase, _result: TestResult, step: TestStep): void {
         | 
| 108 | 
            -
                    const testUUID = this.tests.get(test.id);
         | 
| 109 | 
            -
                    const stepUUID = this.steps.get(test.id + "|" + step.titlePath())
         | 
| 110 | 
            -
                    if(step.error) {
         | 
| 111 | 
            -
                        const message = step.error.message;
         | 
| 112 | 
            -
                        this.client.log({
         | 
| 113 | 
            -
                            logFormat: LogFormat.MARKDOWN,
         | 
| 114 | 
            -
                            logLevel: LogLevel.ERROR,
         | 
| 115 | 
            -
                            logTime: getTime(),
         | 
| 116 | 
            -
                            message: ansiToMarkdown(message),
         | 
| 117 | 
            -
                            testRunUUID: this.testRunId,
         | 
| 118 | 
            -
                            testUUID: testUUID,
         | 
| 119 | 
            -
                            stepUUID: stepUUID
         | 
| 120 | 
            -
                        });
         | 
| 121 | 
            -
             | 
| 122 | 
            -
                        if (step.error.snippet) {
         | 
| 123 | 
            -
                            this.client.log({
         | 
| 124 | 
            -
                                logFormat: LogFormat.MARKDOWN,
         | 
| 125 | 
            -
                                logLevel: LogLevel.ERROR,
         | 
| 126 | 
            -
                                logTime: getTime(),
         | 
| 127 | 
            -
                                message: `\`\`\`js\n${removeAnsi(step.error.snippet)}\n\`\`\``,
         | 
| 128 | 
            -
                                testRunUUID: this.testRunId,
         | 
| 129 | 
            -
                                testUUID: testUUID,
         | 
| 130 | 
            -
                                stepUUID: stepUUID
         | 
| 131 | 
            -
                            });
         | 
| 132 | 
            -
                        }
         | 
| 133 | 
            -
                    }
         | 
| 134 | 
            -
             | 
| 135 | 
            -
                    this.client.finishStep(this.steps.get(test.id + "|" + step.titlePath()), {
         | 
| 136 | 
            -
                        endTime: getTime(),
         | 
| 137 | 
            -
                        status: step.error ? Status.FAILED : Status.PASSED,
         | 
| 138 | 
            -
                        testRunUUID: this.testRunId
         | 
| 139 | 
            -
                    })
         | 
| 140 | 
            -
                    this.steps.delete(test.id + "|" + step.titlePath())
         | 
| 141 | 
            -
                }
         | 
| 142 | 
            -
             | 
| 143 | 
            -
                onTestBegin(test: TestCase): void {
         | 
| 144 | 
            -
                    //check suite
         | 
| 145 | 
            -
                    const suiteUUID = this.getOrStartSuite(test.parent.titlePath())
         | 
| 146 | 
            -
                    const attributes: Array<Attribute> = [];
         | 
| 147 | 
            -
                    for (const tag of test.tags) {
         | 
| 148 | 
            -
                        attributes.push({value: tag})
         | 
| 149 | 
            -
                    }
         | 
| 150 | 
            -
                    const testUUID = this.client.startTest({
         | 
| 151 | 
            -
                        testType: TestType.TEST,
         | 
| 152 | 
            -
                        testRunUUID: this.testRunId,
         | 
| 153 | 
            -
                        suiteUUID: suiteUUID,
         | 
| 154 | 
            -
                        testName: test.title,
         | 
| 155 | 
            -
                        startTime: getTime(),
         | 
| 156 | 
            -
                        description: this.getTestDescription(test),
         | 
| 157 | 
            -
                        attributes: attributes
         | 
| 158 | 
            -
                    });
         | 
| 159 | 
            -
                    this.tests.set(test.id, testUUID);
         | 
| 160 | 
            -
                }
         | 
| 161 | 
            -
             | 
| 162 | 
            -
                async onTestEnd(test: TestCase, result: TestResult): Promise<void> {
         | 
| 163 | 
            -
                    const testUUID = this.tests.get(test.id);
         | 
| 164 | 
            -
                    if (result.attachments.length > 0) {
         | 
| 165 | 
            -
                        let message = "";
         | 
| 166 | 
            -
                        for (const attachment of result.attachments) {
         | 
| 167 | 
            -
                            message += `- ${attachment.name} (${attachment.contentType})\n`
         | 
| 168 | 
            -
                        }
         | 
| 169 | 
            -
                        const attachmentsLogUUID = this.client.log({
         | 
| 170 | 
            -
                            logFormat: LogFormat.MARKDOWN,
         | 
| 171 | 
            -
                            logLevel: LogLevel.INFO,
         | 
| 172 | 
            -
                            logTime: getTime(),
         | 
| 173 | 
            -
                            message: message,
         | 
| 174 | 
            -
                            testRunUUID: this.testRunId,
         | 
| 175 | 
            -
                            testUUID: testUUID
         | 
| 176 | 
            -
                        })
         | 
| 177 | 
            -
                        for (const attachment of result.attachments) {
         | 
| 178 | 
            -
                            this.promises.push(this.logAttachment(attachment, testUUID, attachmentsLogUUID));
         | 
| 179 | 
            -
                        }
         | 
| 180 | 
            -
                    }
         | 
| 181 | 
            -
             | 
| 182 | 
            -
                    //determine status
         | 
| 183 | 
            -
                    const status = testStatusMap[result.status]
         | 
| 184 | 
            -
             | 
| 185 | 
            -
                    //finish test
         | 
| 186 | 
            -
                    this.client.finishTest(testUUID, {
         | 
| 187 | 
            -
                        testRunUUID: this.testRunId,
         | 
| 188 | 
            -
                        status: status,
         | 
| 189 | 
            -
                        endTime: getTime()
         | 
| 190 | 
            -
                    });
         | 
| 191 | 
            -
                    this.tests.delete(test.id);
         | 
| 192 | 
            -
                }
         | 
| 193 | 
            -
             | 
| 194 | 
            -
                printsToStdio(): boolean {
         | 
| 195 | 
            -
                    return false;
         | 
| 196 | 
            -
                }
         | 
| 197 | 
            -
             | 
| 198 | 
            -
                private getOrStartSuite(suitePath: Array<string>): UUID {
         | 
| 199 | 
            -
                    const filteredSuitePath = suitePath.filter(name => name !== "");
         | 
| 200 | 
            -
                    let currentPath: Array<string> = [];
         | 
| 201 | 
            -
                    let parentSuiteUUID: UUID | undefined = undefined;
         | 
| 202 | 
            -
             | 
| 203 | 
            -
                    for (const suiteName of filteredSuitePath) {
         | 
| 204 | 
            -
                        currentPath.push(suiteName);
         | 
| 205 | 
            -
                        const existingSuiteUUID = this.suites.get(currentPath.join('|'));
         | 
| 206 | 
            -
             | 
| 207 | 
            -
                        if (existingSuiteUUID) {
         | 
| 208 | 
            -
                            parentSuiteUUID = existingSuiteUUID;
         | 
| 209 | 
            -
                        } else {
         | 
| 210 | 
            -
                            const newSuitesUUIDs = this.client.startSuite({
         | 
| 211 | 
            -
                                testRunUUID: this.testRunId,
         | 
| 212 | 
            -
                                parentSuiteUUID: parentSuiteUUID,
         | 
| 213 | 
            -
                                suiteNames: [suiteName],
         | 
| 214 | 
            -
                            });
         | 
| 215 | 
            -
             | 
| 216 | 
            -
                            if (newSuitesUUIDs && newSuitesUUIDs.length > 0) {
         | 
| 217 | 
            -
                                parentSuiteUUID = newSuitesUUIDs[0];
         | 
| 218 | 
            -
                                this.suites.set(currentPath.join('|'), parentSuiteUUID);
         | 
| 219 | 
            -
                            } else {
         | 
| 220 | 
            -
                                console.error(`Failed to create suite for path: ${currentPath.join(' > ')}`);
         | 
| 221 | 
            -
                            }
         | 
| 222 | 
            -
                        }
         | 
| 223 | 
            -
                    }
         | 
| 224 | 
            -
                    return parentSuiteUUID as UUID;
         | 
| 225 | 
            -
                }
         | 
| 226 | 
            -
             | 
| 227 | 
            -
                private getTestDescription(test: TestCase): string {
         | 
| 228 | 
            -
                    let description = `${path.basename(test.location.file)}:${test.location.line}\n`;
         | 
| 229 | 
            -
                    for (const annotation of test.annotations) {
         | 
| 230 | 
            -
                        description = `${description + annotation.type}: ${annotation.description}\n`
         | 
| 231 | 
            -
                    }
         | 
| 232 | 
            -
                    return description;
         | 
| 233 | 
            -
                }
         | 
| 234 | 
            -
             | 
| 235 | 
            -
                private async logAttachment(attachment: {
         | 
| 236 | 
            -
                    name: string,
         | 
| 237 | 
            -
                    path?: string,
         | 
| 238 | 
            -
                    body?: Buffer,
         | 
| 239 | 
            -
                    contentType: string
         | 
| 240 | 
            -
                }, testUUID: UUID, logUUID: UUID) {
         | 
| 241 | 
            -
                    let content: Buffer;
         | 
| 242 | 
            -
                    if (attachment.body) {
         | 
| 243 | 
            -
                        content = attachment.body;
         | 
| 244 | 
            -
                    } else if (attachment.path) {
         | 
| 245 | 
            -
                        content = await getBytes(attachment.path);
         | 
| 246 | 
            -
                    } else {
         | 
| 247 | 
            -
                        throw new Error("Attachment must have either body or path defined.");
         | 
| 248 | 
            -
                    }
         | 
| 249 | 
            -
             | 
| 250 | 
            -
                    const orangebeardAttachment: Attachment = {
         | 
| 251 | 
            -
                        file: {
         | 
| 252 | 
            -
                            name: path.basename(attachment.path),
         | 
| 253 | 
            -
                            content: content,
         | 
| 254 | 
            -
                            contentType: attachment.contentType,
         | 
| 255 | 
            -
                        },
         | 
| 256 | 
            -
                        metaData: {
         | 
| 257 | 
            -
                            testRunUUID: this.testRunId,
         | 
| 258 | 
            -
                            testUUID: testUUID,
         | 
| 259 | 
            -
                            logUUID: logUUID,
         | 
| 260 | 
            -
                            attachmentTime: getTime()
         | 
| 261 | 
            -
                        },
         | 
| 262 | 
            -
                    };
         | 
| 263 | 
            -
                    this.client.sendAttachment(orangebeardAttachment);
         | 
| 264 | 
            -
                }
         | 
| 265 | 
            -
            }
         | 
    
        package/src/reporter/utils.ts
    DELETED
    
    | @@ -1,160 +0,0 @@ | |
| 1 | 
            -
            import {ZonedDateTime} from "@js-joda/core";
         | 
| 2 | 
            -
            import {FinishTest} from "@orangebeard-io/javascript-client/dist/client/models/FinishTest";
         | 
| 3 | 
            -
            import * as fs from "node:fs";
         | 
| 4 | 
            -
            import {promisify} from "util";
         | 
| 5 | 
            -
            import Status = FinishTest.Status;
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            const stat = promisify(fs.stat);
         | 
| 8 | 
            -
            const access = promisify(fs.access);
         | 
| 9 | 
            -
             | 
| 10 | 
            -
            export function getTime() {
         | 
| 11 | 
            -
                return ZonedDateTime.now().withFixedOffsetZone().toString();
         | 
| 12 | 
            -
            }
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            export const testStatusMap = {
         | 
| 15 | 
            -
                "passed": Status.PASSED,
         | 
| 16 | 
            -
                "failed": Status.FAILED,
         | 
| 17 | 
            -
                "timedOut": Status.TIMED_OUT,
         | 
| 18 | 
            -
                "skipped": Status.SKIPPED,
         | 
| 19 | 
            -
                "interrupted": Status.STOPPED
         | 
| 20 | 
            -
            };
         | 
| 21 | 
            -
             | 
| 22 | 
            -
            export function removeAnsi(ansiString: string): string {
         | 
| 23 | 
            -
                const parts = ansiString.split(/(\u001b\[[0-9;]*[mG])/);
         | 
| 24 | 
            -
                let result = "";
         | 
| 25 | 
            -
                for (const part of parts) {
         | 
| 26 | 
            -
                    if (!part.startsWith("\u001b[")) {
         | 
| 27 | 
            -
                        result += part;
         | 
| 28 | 
            -
                    }
         | 
| 29 | 
            -
                }
         | 
| 30 | 
            -
                return result;
         | 
| 31 | 
            -
            }
         | 
| 32 | 
            -
             | 
| 33 | 
            -
            export function ansiToMarkdown(ansiString: string): string {
         | 
| 34 | 
            -
                let markdown = "";
         | 
| 35 | 
            -
                let currentStyle: { italic?: boolean, code?: boolean } = {};
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                const ansiCodes = {
         | 
| 38 | 
            -
                    "31": {italic: true},
         | 
| 39 | 
            -
                    "32": {italic: true},
         | 
| 40 | 
            -
                    "39": {italic: false}, // Reset styles
         | 
| 41 | 
            -
                    "2": {code: true},
         | 
| 42 | 
            -
                    "22": {code: false},
         | 
| 43 | 
            -
                };
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                const parts = ansiString.split(/(\u001b\[[0-9;]*[mG])/);
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                for (const part of parts) {
         | 
| 48 | 
            -
                    if (part.startsWith("\u001b[")) {
         | 
| 49 | 
            -
                        const code = part.slice(2, -1);
         | 
| 50 | 
            -
                        const codes = code.split(';');
         | 
| 51 | 
            -
                        for (const c of codes) {
         | 
| 52 | 
            -
                            const style = ansiCodes[c as keyof typeof ansiCodes]; // Type guard
         | 
| 53 | 
            -
                            if (style) {
         | 
| 54 | 
            -
                                currentStyle = {...currentStyle, ...style};
         | 
| 55 | 
            -
                            }
         | 
| 56 | 
            -
                        }
         | 
| 57 | 
            -
                    } else {
         | 
| 58 | 
            -
                        let formattedPart = part.replace(/\n/g, "  \n");
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                        if (currentStyle.italic) {
         | 
| 61 | 
            -
                            formattedPart = formattedPart.endsWith(" ") ? `*${formattedPart.trim()}* ` : `*${formattedPart}*`;
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                        }
         | 
| 64 | 
            -
                        if (currentStyle.code) {
         | 
| 65 | 
            -
                            formattedPart = `${formattedPart}`;
         | 
| 66 | 
            -
                        }
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                        markdown += formattedPart
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                    }
         | 
| 71 | 
            -
                }
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                return markdown;
         | 
| 74 | 
            -
            }
         | 
| 75 | 
            -
             | 
| 76 | 
            -
            /**
         | 
| 77 | 
            -
             * Reads a 3-line snippet from a file, centered around the specified line number.
         | 
| 78 | 
            -
             *
         | 
| 79 | 
            -
             * @param filePath - The path to the file.
         | 
| 80 | 
            -
             * @param lineNumber - The line number to center the snippet around (1-based index).
         | 
| 81 | 
            -
             * @returns A promise that resolves with the 3-line snippet or an error message if the line is out of range.
         | 
| 82 | 
            -
             */
         | 
| 83 | 
            -
            export /**
         | 
| 84 | 
            -
             * Reads a 3-line snippet from a file, centered around the specified line number.
         | 
| 85 | 
            -
             *
         | 
| 86 | 
            -
             * @param filePath - The path to the file.
         | 
| 87 | 
            -
             * @param lineNumber - The line number to center the snippet around (1-based index).
         | 
| 88 | 
            -
             * @returns The 3-line snippet or an error message if the line is out of range.
         | 
| 89 | 
            -
             */
         | 
| 90 | 
            -
            function getCodeSnippet(filePath: string, lineNumber: number): string {
         | 
| 91 | 
            -
                if (lineNumber < 1) {
         | 
| 92 | 
            -
                    throw new Error('Line number must be 1 or greater.');
         | 
| 93 | 
            -
                }
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                const fileContent = fs.readFileSync(filePath, 'utf8');
         | 
| 96 | 
            -
                const lines = fileContent.split(/\r?\n/); // Support both Unix and Windows line endings
         | 
| 97 | 
            -
             | 
| 98 | 
            -
                const startLine = Math.max(0, lineNumber - 2); // Zero-based index for one line before
         | 
| 99 | 
            -
                const endLine = Math.min(lines.length, lineNumber + 1); // One line after
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                if (startLine >= lines.length) {
         | 
| 102 | 
            -
                    throw new Error('Line number is out of range.');
         | 
| 103 | 
            -
                }
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                let snippet = lines.slice(startLine, endLine);
         | 
| 106 | 
            -
                if (snippet.length > 0 && snippet[0].trim() === "") {
         | 
| 107 | 
            -
                    snippet = snippet.slice(1);
         | 
| 108 | 
            -
                }
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                return `\`\`\`js\n${snippet.join('\n')}\n\`\`\``;
         | 
| 111 | 
            -
            }
         | 
| 112 | 
            -
             | 
| 113 | 
            -
            const fileExists = async (filepath: string) => {
         | 
| 114 | 
            -
                try {
         | 
| 115 | 
            -
                    await access(filepath, fs.constants.F_OK);
         | 
| 116 | 
            -
                    return true;
         | 
| 117 | 
            -
                } catch {
         | 
| 118 | 
            -
                    return false;
         | 
| 119 | 
            -
                }
         | 
| 120 | 
            -
            };
         | 
| 121 | 
            -
             | 
| 122 | 
            -
            const waitForFile = async (filepath: string, interval = 1000, timeout = 60000) => {
         | 
| 123 | 
            -
                const start = Date.now();
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                while (true) {
         | 
| 126 | 
            -
                    const now = Date.now();
         | 
| 127 | 
            -
                    if (now - start > timeout) {
         | 
| 128 | 
            -
                        throw new Error(`Timeout: ${filepath} did not become available within ${timeout}ms`);
         | 
| 129 | 
            -
                    }
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                    if (await fileExists(filepath)) {
         | 
| 132 | 
            -
                        const stats = [];
         | 
| 133 | 
            -
                        for (let i = 0; i < 2; i++) {
         | 
| 134 | 
            -
                            stats.push(await stat(filepath));
         | 
| 135 | 
            -
                            await new Promise((resolve) => setTimeout(resolve, interval));
         | 
| 136 | 
            -
                        }
         | 
| 137 | 
            -
             | 
| 138 | 
            -
                        const [first, second] = stats;
         | 
| 139 | 
            -
                        if (
         | 
| 140 | 
            -
                            first.mtimeMs === second.mtimeMs &&
         | 
| 141 | 
            -
                            first.size === second.size
         | 
| 142 | 
            -
                        ) {
         | 
| 143 | 
            -
                            return;
         | 
| 144 | 
            -
                        }
         | 
| 145 | 
            -
                    }
         | 
| 146 | 
            -
             | 
| 147 | 
            -
                    await new Promise((resolve) => setTimeout(resolve, interval));
         | 
| 148 | 
            -
                }
         | 
| 149 | 
            -
            };
         | 
| 150 | 
            -
             | 
| 151 | 
            -
            export const getBytes = async (filePath: string) => {
         | 
| 152 | 
            -
                try {
         | 
| 153 | 
            -
                    await waitForFile(filePath, 100, 5000)
         | 
| 154 | 
            -
                    return fs.readFileSync(filePath);
         | 
| 155 | 
            -
                } catch (err) {
         | 
| 156 | 
            -
                    console.error('Error reading file:', err);
         | 
| 157 | 
            -
                    throw err;
         | 
| 158 | 
            -
                }
         | 
| 159 | 
            -
            };
         | 
| 160 | 
            -
             | 
    
        package/tsconfig.json
    DELETED
    
    | @@ -1,20 +0,0 @@ | |
| 1 | 
            -
            {
         | 
| 2 | 
            -
              "compilerOptions": {
         | 
| 3 | 
            -
                "target": "es6",
         | 
| 4 | 
            -
                "module": "commonjs",
         | 
| 5 | 
            -
                "allowJs": false,
         | 
| 6 | 
            -
                "outDir": "dist",
         | 
| 7 | 
            -
                "rootDir": "src",
         | 
| 8 | 
            -
                "noImplicitAny": true,
         | 
| 9 | 
            -
                "esModuleInterop": true,
         | 
| 10 | 
            -
                "resolveJsonModule": true,
         | 
| 11 | 
            -
                "moduleResolution": "node",
         | 
| 12 | 
            -
                "baseUrl": ".",
         | 
| 13 | 
            -
                "paths": {
         | 
| 14 | 
            -
                  "*": ["node_modules/*"]
         | 
| 15 | 
            -
                },
         | 
| 16 | 
            -
                "typeRoots": ["./node_modules/@types"]
         | 
| 17 | 
            -
              },
         | 
| 18 | 
            -
              "include": ["./src/**/*"],
         | 
| 19 | 
            -
              "exclude": ["node_modules"],
         | 
| 20 | 
            -
            }
         |