@testream/vitest-reporter 1.0.0 → 1.1.0

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/README.md CHANGED
@@ -25,4 +25,4 @@ export default defineConfig({
25
25
  })
26
26
  ```
27
27
 
28
- Need more configuration options? See the full guide at https://testream.github.io/docs/reporters/vitest.
28
+ Need more configuration options? See the full guide at https://docs.testream.app/reporters/vitest.
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- (()=>{"use strict";var e={406:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t.detectCIContext=detectCIContext;function detectCIContext(){const e=process.env;if(e.GITHUB_ACTIONS==="true"){return{branch:e.GITHUB_HEAD_REF||e.GITHUB_REF_NAME||e.GITHUB_REF?.replace("refs/heads/",""),commitSha:e.GITHUB_SHA,repositoryUrl:e.GITHUB_SERVER_URL&&e.GITHUB_REPOSITORY?`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}`:undefined,buildNumber:e.GITHUB_RUN_NUMBER,buildUrl:e.GITHUB_SERVER_URL&&e.GITHUB_REPOSITORY&&e.GITHUB_RUN_ID?`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}/actions/runs/${e.GITHUB_RUN_ID}`:undefined}}if(e.GITLAB_CI==="true"){return{branch:e.CI_COMMIT_BRANCH||e.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME,commitSha:e.CI_COMMIT_SHA,repositoryUrl:e.CI_PROJECT_URL,buildNumber:e.CI_PIPELINE_IID,buildUrl:e.CI_PIPELINE_URL}}if(e.TF_BUILD==="True"){return{branch:e.BUILD_SOURCEBRANCH?.replace("refs/heads/",""),commitSha:e.BUILD_SOURCEVERSION,repositoryUrl:e.BUILD_REPOSITORY_URI,buildNumber:e.BUILD_BUILDNUMBER,buildUrl:e.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI&&e.SYSTEM_TEAMPROJECT&&e.BUILD_BUILDID?`${e.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${e.SYSTEM_TEAMPROJECT}/_build/results?buildId=${e.BUILD_BUILDID}`:undefined}}if(e.CIRCLECI==="true"){return{branch:e.CIRCLE_BRANCH,commitSha:e.CIRCLE_SHA1,repositoryUrl:e.CIRCLE_REPOSITORY_URL,buildNumber:e.CIRCLE_BUILD_NUM,buildUrl:e.CIRCLE_BUILD_URL}}if(e.JENKINS_URL){return{branch:e.GIT_BRANCH?.replace("origin/",""),commitSha:e.GIT_COMMIT,repositoryUrl:e.GIT_URL,buildNumber:e.BUILD_NUMBER,buildUrl:e.BUILD_URL}}if(e.BITBUCKET_BUILD_NUMBER){return{branch:e.BITBUCKET_BRANCH,commitSha:e.BITBUCKET_COMMIT,repositoryUrl:e.BITBUCKET_GIT_HTTP_ORIGIN,buildNumber:e.BITBUCKET_BUILD_NUMBER,buildUrl:e.BITBUCKET_REPO_FULL_NAME&&e.BITBUCKET_BUILD_NUMBER?`https://bitbucket.org/${e.BITBUCKET_REPO_FULL_NAME}/pipelines/results/${e.BITBUCKET_BUILD_NUMBER}`:undefined}}return{}}},827:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true})},322:function(e,t,r){var o=this&&this.__createBinding||(Object.create?function(e,t,r,o){if(o===undefined)o=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,o,s)}:function(e,t,r,o){if(o===undefined)o=r;e[o]=t[r]});var s=this&&this.__exportStar||function(e,t){for(var r in e)if(r!=="default"&&!Object.prototype.hasOwnProperty.call(t,r))o(t,e,r)};Object.defineProperty(t,"__esModule",{value:true});t.ensureReportId=t.mapAttachmentsToTestResults=t.uploadArtifacts=t.uploadTestRun=t.detectCIContext=void 0;s(r(827),t);var n=r(406);Object.defineProperty(t,"detectCIContext",{enumerable:true,get:function(){return n.detectCIContext}});var a=r(969);Object.defineProperty(t,"uploadTestRun",{enumerable:true,get:function(){return a.uploadTestRun}});Object.defineProperty(t,"uploadArtifacts",{enumerable:true,get:function(){return a.uploadArtifacts}});Object.defineProperty(t,"mapAttachmentsToTestResults",{enumerable:true,get:function(){return a.mapAttachmentsToTestResults}});Object.defineProperty(t,"ensureReportId",{enumerable:true,get:function(){return a.ensureReportId}})},969:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t.ensureReportId=ensureReportId;t.uploadTestRun=uploadTestRun;t.mapAttachmentsToTestResults=mapAttachmentsToTestResults;t.uploadArtifacts=uploadArtifacts;const o="https://test-manager-backend.fly.dev";function ensureReportId(e){if(typeof e.reportId==="string"&&e.reportId.trim().length>0){return e.reportId}const t=crypto.randomUUID();e.reportId=t;return t}function resolveApiUrl(e){const t=normalizeApiUrl(e);if(t){return t}const r=getEnvApiUrl();if(r){return r}return o}function getEnvApiUrl(){if(typeof process==="undefined"||!process?.env){return undefined}return normalizeApiUrl(process.env.TESTREAM_API_URL)}function normalizeApiUrl(e){if(!e){return undefined}const t=e.trim();if(!t){return undefined}return t.replace(/\/+$/,"")}async function uploadTestRun(e){const{report:t,apiKey:r}=e;const o=resolveApiUrl(e.apiUrl);const s=ensureReportId(t);const n={report:t,reportId:s,commitSha:e.commitSha,branch:e.branch,repositoryUrl:e.repositoryUrl,buildName:e.buildName,buildNumber:e.buildNumber,buildUrl:e.buildUrl,testEnvironment:e.testEnvironment,appName:e.appName,appVersion:e.appVersion,testType:e.testType};console.log("Uploading test results...");let a;try{a=await fetch(`${o}/api/v1/ingest`,{method:"POST",headers:{"X-API-KEY":r,"Content-Type":"application/json"},body:JSON.stringify(n)})}catch(e){const t=e instanceof Error?e.message:String(e);return{success:false,reportId:s,error:`Connection failed: ${t}`}}if(a.status===409){console.warn("Report already exists (workflow may have been re-run)");return{success:true,reportId:s,summary:{passed:t.results.summary.passed,failed:t.results.summary.failed,skipped:t.results.summary.skipped,total:t.results.summary.tests},alreadyExists:true}}if(!a.ok){const e=await a.text();return{success:false,reportId:s,error:`Upload failed (HTTP ${a.status}): ${e}`}}const i=await a.json();console.log(`✓ Test results uploaded successfully`);console.log(` Report ID: ${i.reportId}`);console.log(` Test Run ID: ${i.testRunId}`);console.log(` Tests: ${i.summary.passed}/${i.summary.total} passed`);return{success:true,reportId:i.reportId,testRunId:i.testRunId,summary:{passed:i.summary.passed,failed:i.summary.failed,skipped:i.summary.skipped,total:i.summary.total},testResults:i.testResults}}function mapAttachmentsToTestResults(e,t){const r=new Map;for(const e of t){const t=r.get(e.name)??[];t.push(e.id);r.set(e.name,t)}const o=[];for(const t of e){const e=r.get(t.name);const s=e?.shift();if(!t.attachments||t.attachments.length===0){continue}if(!s){console.warn(`Skipping artifact upload: could not match test result for "${t.name}"`);continue}o.push({testResultId:s,attachments:t.attachments})}return o}async function uploadArtifacts(e){const{reportId:t,apiKey:r,testResults:o}=e;const s=resolveApiUrl(e.apiUrl);let n=0;for(const e of o){for(const o of e.attachments){try{const a=await uploadSingleArtifact({testResultId:e.testResultId,attachment:o,reportId:t,apiKey:r,apiUrl:s});if(a)n++}catch(e){const t=e instanceof Error?e.message:String(e);console.error(`Failed to upload artifact ${o.name}: ${t}`)}}}if(n>0){console.log(`✓ Uploaded ${n} artifact(s)`)}return n}async function uploadSingleArtifact(e){const{testResultId:t,attachment:o,reportId:s,apiKey:n,apiUrl:a}=e;const i=await Promise.resolve().then(r.t.bind(r,943,23));const l=await Promise.resolve().then(r.t.bind(r,928,23));const c=l.resolve(o.path);try{await i.access(c)}catch{console.warn(`Artifact not found: ${l.basename(c)}`);return false}let u;let p;const d=l.basename(c);const f=o.contentType||"application/octet-stream";try{u=await i.readFile(c);p=u.byteLength}catch(e){const t=e instanceof Error?e.message:String(e);throw new Error(`Failed to read file: ${t}`)}try{return await uploadWithPresignedUrl({testResultId:t,reportId:s,apiKey:n,apiUrl:a,attachmentName:o.name,fileName:d,contentType:f,sizeBytes:p,fileBuffer:u})}catch(e){if(!(e instanceof LegacyUploadRequiredError)){throw e}return await uploadWithLegacyEndpoint({testResultId:t,attachmentName:o.name,reportId:s,apiKey:n,apiUrl:a,fileName:d,contentType:f,fileBuffer:u})}}class LegacyUploadRequiredError extends Error{constructor(){super("Legacy upload endpoint required")}}async function uploadWithPresignedUrl(e){const{testResultId:t,reportId:r,apiKey:o,apiUrl:s,attachmentName:n,fileName:a,contentType:i,sizeBytes:l,fileBuffer:c}=e;const u={testResultId:t,ctrfAttachmentName:n,fileName:a,contentType:i,sizeBytes:l};const p=await fetch(`${s}/api/v1/artifacts/${r}/upload-url`,{method:"POST",headers:{"X-API-KEY":o,"Content-Type":"application/json"},body:JSON.stringify(u)});if(shouldFallbackToLegacyUpload(p.status)){throw new LegacyUploadRequiredError}if(!p.ok){const e=await p.text();throw new Error(`Failed to create direct upload URL (HTTP ${p.status}): ${e}`)}const d=await p.json();const f={...d.requiredHeaders??{}};if(!hasHeaderIgnoreCase(f,"Content-Type")){f["Content-Type"]=i}const m=await fetch(d.uploadUrl,{method:"PUT",headers:f,body:c});if(!m.ok){const e=await m.text();throw new Error(`Direct artifact upload failed (HTTP ${m.status}): ${e}`)}const h={testResultId:t,ctrfAttachmentName:n,fileName:a,contentType:i,sizeBytes:l,storageKey:d.storageKey};const _=await fetch(`${s}/api/v1/artifacts/${r}/complete`,{method:"POST",headers:{"X-API-KEY":o,"Content-Type":"application/json"},body:JSON.stringify(h)});if(!_.ok){const e=await _.text();throw new Error(`Failed to finalize artifact upload (HTTP ${_.status}): ${e}`)}return true}async function uploadWithLegacyEndpoint(e){const{testResultId:t,attachmentName:r,reportId:o,apiKey:s,apiUrl:n,fileName:a,contentType:i,fileBuffer:l}=e;const c=new Blob([new Uint8Array(l)],{type:i});const u=new FormData;u.append("testResultId",t);u.append("ctrfAttachmentName",r);u.append("file",c,a);const p=await fetch(`${n}/api/v1/artifacts/${o}`,{method:"POST",headers:{"X-API-KEY":s},body:u});if(!p.ok){const e=await p.text();throw new Error(`Legacy artifact upload failed (HTTP ${p.status}): ${e}`)}return true}function shouldFallbackToLegacyUpload(e){return e===404||e===405||e===501}function hasHeaderIgnoreCase(e,t){const r=t.toLowerCase();return Object.keys(e).some((e=>e.toLowerCase()===r))}},943:e=>{e.exports=require("fs/promises")},928:e=>{e.exports=require("path")}};var t={};function __nccwpck_require__(r){var o=t[r];if(o!==undefined){return o.exports}var s=t[r]={exports:{}};var n=true;try{e[r].call(s.exports,s,s.exports,__nccwpck_require__);n=false}finally{if(n)delete t[r]}return s.exports}(()=>{var e=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;var t;__nccwpck_require__.t=function(r,o){if(o&1)r=this(r);if(o&8)return r;if(typeof r==="object"&&r){if(o&4&&r.__esModule)return r;if(o&16&&typeof r.then==="function")return r}var s=Object.create(null);__nccwpck_require__.r(s);var n={};t=t||[null,e({}),e([]),e(e)];for(var a=o&2&&r;typeof a=="object"&&!~t.indexOf(a);a=e(a)){Object.getOwnPropertyNames(a).forEach((e=>n[e]=()=>r[e]))}n["default"]=()=>r;__nccwpck_require__.d(s,n);return s}})();(()=>{__nccwpck_require__.d=(e,t)=>{for(var r in t){if(__nccwpck_require__.o(t,r)&&!__nccwpck_require__.o(e,r)){Object.defineProperty(e,r,{enumerable:true,get:t[r]})}}}})();(()=>{__nccwpck_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t)})();(()=>{__nccwpck_require__.r=e=>{if(typeof Symbol!=="undefined"&&Symbol.toStringTag){Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})}Object.defineProperty(e,"__esModule",{value:true})}})();if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var r={};__nccwpck_require__.r(r);__nccwpck_require__.d(r,{TestreamVitestReporter:()=>TestreamVitestReporter,default:()=>TestreamVitestReporter});var o=__nccwpck_require__(943);var s=__nccwpck_require__(928);var n=__nccwpck_require__(322);function mapStatus(e){switch(e){case"passed":return"passed";case"failed":return"failed";case"skipped":return"skipped";default:return"pending"}}function buildSuiteName(e){const t=[];let r=e.parent;while(r&&r.type==="suite"){t.unshift(r.name);r=r.parent}return t.join(" > ")}function collectTests(e){const t=[];for(const r of e){if(r.type==="test"){t.push(r)}else if(r.type==="suite"){t.push(...collectTests(r.children))}}return t}function buildCTRFReport(e,t,r){const o=Date.now();const s=[];const n=new Set;for(const o of e){const e=collectTests(o.children);for(const o of e){const e=o.result();const a=o.diagnostic();const i=e.state;const l=mapStatus(i);const c=Math.round(a?.duration??0);const u=a?.startTime??r;const p=u+c;const d=a?.retryCount??0;const f=a?.flaky??false;const m=buildSuiteName(o);if(m){n.add(m)}let h;let _;const b=e.errors;if(b&&b.length>0){const e=b[0];h=e.message;const t=e.stackTrace??e.stack;_=typeof t==="string"?t:undefined}const y={name:o.name,status:l,duration:c,start:u,stop:p,rawStatus:i,tags:[],type:t.testType||"unit",filePath:o.module.moduleId,retries:d,flaky:f,steps:[],suite:m||undefined,stdout:[],stderr:[],message:h,trace:_};s.push(y)}}const a={tests:s.length,passed:s.filter((e=>e.status==="passed")).length,failed:s.filter((e=>e.status==="failed")).length,skipped:s.filter((e=>e.status==="skipped")).length,pending:s.filter((e=>e.status==="pending")).length,other:s.filter((e=>e.status==="other")).length,suites:n.size,start:r,stop:o};const i={reportFormat:"CTRF",specVersion:"0.0.1",timestamp:new Date(r).toISOString(),generatedBy:"@testream/vitest-reporter",extra:{branch:t.branch,commitSha:t.commitSha},results:{tool:{name:"vitest"},summary:a,tests:s,environment:{...t.testEnvironment?{testEnvironment:t.testEnvironment}:{},...t.appName?{appName:t.appName}:{},...t.appVersion?{appVersion:t.appVersion}:{},...t.buildName?{buildName:t.buildName}:{},...t.buildNumber?{buildNumber:t.buildNumber}:{},...t.buildUrl?{buildUrl:t.buildUrl}:{}}}};return i}class ReportUploader{constructor(e){this.config={apiKey:e.apiKey,branch:e.branch,commitSha:e.commitSha,repositoryUrl:e.repositoryUrl,failOnUploadError:e.failOnUploadError??false,buildName:e.buildName,buildNumber:e.buildNumber,buildUrl:e.buildUrl,testEnvironment:e.testEnvironment,appName:e.appName,appVersion:e.appVersion,testType:e.testType}}async uploadReport(e){try{const t=await(0,n.uploadTestRun)({report:e,apiKey:this.config.apiKey,commitSha:this.config.commitSha,branch:this.config.branch,repositoryUrl:this.config.repositoryUrl,buildName:this.config.buildName,buildNumber:this.config.buildNumber,buildUrl:this.config.buildUrl,testEnvironment:this.config.testEnvironment,appName:this.config.appName,appVersion:this.config.appVersion,testType:this.config.testType});if(!t.success){if(this.config.failOnUploadError){throw new Error(t.error||"Upload failed")}return t}let r=0;if(!t.alreadyExists&&t.testRunId&&t.testResults){const o=(0,n.mapAttachmentsToTestResults)(e.results.tests,t.testResults);if(o.length>0){r=await(0,n.uploadArtifacts)({reportId:t.reportId,apiKey:this.config.apiKey,testResults:o})}}return{...t,artifactCount:r}}catch(t){const r=t instanceof Error?t.message:String(t);if(this.config.failOnUploadError){throw new Error(`Failed to upload report: ${r}`)}return{success:false,reportId:(0,n.ensureReportId)(e),error:r}}}}class TestreamVitestReporter{constructor(e){this.uploader=null;this.startTimestamp=0;if(!e.apiKey){throw new Error("TestreamVitestReporter: apiKey is required")}this.config={uploadEnabled:true,outputFile:"ctrf-report.json",outputDir:"ctrf",failOnUploadError:false,testType:"unit",...e};const t=(0,n.detectCIContext)();if(!this.config.branch&&t.branch){this.config.branch=t.branch}if(!this.config.commitSha&&t.commitSha){this.config.commitSha=t.commitSha}if(!this.config.repositoryUrl&&t.repositoryUrl){this.config.repositoryUrl=t.repositoryUrl}if(!this.config.buildNumber&&t.buildNumber){this.config.buildNumber=t.buildNumber}if(!this.config.buildUrl&&t.buildUrl){this.config.buildUrl=t.buildUrl}this.reportPath=s.join(this.config.outputDir,this.config.outputFile);if(this.config.uploadEnabled){this.uploader=new ReportUploader(this.config)}}onTestRunStart(e){this.startTimestamp=Date.now();console.log("");console.log("=".repeat(60));console.log("Vitest Testream Reporter");console.log("=".repeat(60));if(this.config.uploadEnabled){if(this.config.branch)console.log(`Branch: ${this.config.branch}`);if(this.config.commitSha)console.log(`Commit: ${this.config.commitSha.substring(0,7)}`);if(this.config.repositoryUrl)console.log(`Repository: ${this.config.repositoryUrl}`)}else{console.log("Upload: Disabled")}console.log(`Report: ${this.reportPath}`);console.log("=".repeat(60));console.log("")}async onTestRunEnd(e,t,r){const s=buildCTRFReport(e,this.config,this.startTimestamp);try{await o.mkdir(this.config.outputDir,{recursive:true});await o.writeFile(this.reportPath,JSON.stringify(s,null,2))}catch(e){const t=e instanceof Error?e.message:String(e);console.error(`Failed to write CTRF report: ${t}`)}if(!this.config.uploadEnabled||!this.uploader){console.log("");console.log("CTRF report generated");console.log(` ${this.reportPath}`);return}console.log("");console.log("=".repeat(60));console.log("Uploading Test Results");console.log("=".repeat(60));try{const e=await this.uploader.uploadReport(s);if(e.success){console.log("=".repeat(60));console.log("Upload Complete");console.log("=".repeat(60));console.log("")}else{console.error("Upload completed with errors");console.error("")}}catch(e){const t=e instanceof Error?e.message:String(e);console.error("");console.error("=".repeat(60));console.error("Upload Failed");console.error("=".repeat(60));console.error(`Error: ${t}`);console.error("");if(this.config.failOnUploadError){throw e}}}}const a=null&&TestreamVitestReporter;module.exports=r})();
1
+ (()=>{"use strict";var e={406:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true});t.detectCIContext=detectCIContext;function removePrefix(e,t){if(!e){return undefined}return e.startsWith(t)?e.slice(t.length):e}function readEnvironment(){const e=globalThis;return e.process?.env??{}}function buildGithubRepositoryUrl(e){if(!e.GITHUB_SERVER_URL||!e.GITHUB_REPOSITORY){return undefined}return`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}`}function buildGithubBuildUrl(e){if(!e.GITHUB_SERVER_URL||!e.GITHUB_REPOSITORY||!e.GITHUB_RUN_ID){return undefined}return`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}/actions/runs/${e.GITHUB_RUN_ID}`}function detectGitHubBranch(e){if(e.GITHUB_HEAD_REF){return e.GITHUB_HEAD_REF}if(e.GITHUB_REF?.startsWith("refs/heads/")){return e.GITHUB_REF_NAME??removePrefix(e.GITHUB_REF,"refs/heads/")}return undefined}function detectGitHubActionsContext(e){return{branch:detectGitHubBranch(e),commitSha:e.GITHUB_SHA,repositoryUrl:buildGithubRepositoryUrl(e),buildNumber:e.GITHUB_RUN_NUMBER,buildUrl:buildGithubBuildUrl(e)}}function detectGitLabContext(e){return{branch:e.CI_COMMIT_BRANCH||e.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME,commitSha:e.CI_COMMIT_SHA,repositoryUrl:e.CI_PROJECT_URL,buildNumber:e.CI_PIPELINE_IID,buildUrl:e.CI_PIPELINE_URL}}function detectAzurePipelinesContext(e){return{branch:removePrefix(e.BUILD_SOURCEBRANCH,"refs/heads/"),commitSha:e.BUILD_SOURCEVERSION,repositoryUrl:e.BUILD_REPOSITORY_URI,buildNumber:e.BUILD_BUILDNUMBER,buildUrl:e.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI&&e.SYSTEM_TEAMPROJECT&&e.BUILD_BUILDID?`${e.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${e.SYSTEM_TEAMPROJECT}/_build/results?buildId=${e.BUILD_BUILDID}`:undefined}}function detectCircleCIContext(e){return{branch:e.CIRCLE_BRANCH,commitSha:e.CIRCLE_SHA1,repositoryUrl:e.CIRCLE_REPOSITORY_URL,buildNumber:e.CIRCLE_BUILD_NUM,buildUrl:e.CIRCLE_BUILD_URL}}function detectJenkinsContext(e){return{branch:removePrefix(e.GIT_BRANCH,"origin/"),commitSha:e.GIT_COMMIT,repositoryUrl:e.GIT_URL,buildNumber:e.BUILD_NUMBER,buildUrl:e.BUILD_URL}}function detectBitbucketContext(e){return{branch:e.BITBUCKET_BRANCH,commitSha:e.BITBUCKET_COMMIT,repositoryUrl:e.BITBUCKET_GIT_HTTP_ORIGIN,buildNumber:e.BITBUCKET_BUILD_NUMBER,buildUrl:e.BITBUCKET_REPO_FULL_NAME&&e.BITBUCKET_BUILD_NUMBER?`https://bitbucket.org/${e.BITBUCKET_REPO_FULL_NAME}/pipelines/results/${e.BITBUCKET_BUILD_NUMBER}`:undefined}}const r=[{isMatch:e=>e.GITHUB_ACTIONS==="true",detect:detectGitHubActionsContext},{isMatch:e=>e.GITLAB_CI==="true",detect:detectGitLabContext},{isMatch:e=>e.TF_BUILD==="True",detect:detectAzurePipelinesContext},{isMatch:e=>e.CIRCLECI==="true",detect:detectCircleCIContext},{isMatch:e=>Boolean(e.JENKINS_URL),detect:detectJenkinsContext},{isMatch:e=>Boolean(e.BITBUCKET_BUILD_NUMBER),detect:detectBitbucketContext}];function detectCIContext(){const e=readEnvironment();for(const t of r){if(t.isMatch(e)){return t.detect(e)}}return{}}},827:(e,t)=>{Object.defineProperty(t,"__esModule",{value:true})},322:function(e,t,r){var o=this&&this.__createBinding||(Object.create?function(e,t,r,o){if(o===undefined)o=r;var n=Object.getOwnPropertyDescriptor(t,r);if(!n||("get"in n?!t.__esModule:n.writable||n.configurable)){n={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,o,n)}:function(e,t,r,o){if(o===undefined)o=r;e[o]=t[r]});var n=this&&this.__exportStar||function(e,t){for(var r in e)if(r!=="default"&&!Object.prototype.hasOwnProperty.call(t,r))o(t,e,r)};Object.defineProperty(t,"__esModule",{value:true});t.ensureReportId=t.mapAttachmentsToTestResults=t.uploadArtifacts=t.uploadTestRun=t.detectCIContext=void 0;n(r(827),t);var s=r(406);Object.defineProperty(t,"detectCIContext",{enumerable:true,get:function(){return s.detectCIContext}});var i=r(969);Object.defineProperty(t,"uploadTestRun",{enumerable:true,get:function(){return i.uploadTestRun}});Object.defineProperty(t,"uploadArtifacts",{enumerable:true,get:function(){return i.uploadArtifacts}});Object.defineProperty(t,"mapAttachmentsToTestResults",{enumerable:true,get:function(){return i.mapAttachmentsToTestResults}});Object.defineProperty(t,"ensureReportId",{enumerable:true,get:function(){return i.ensureReportId}})},969:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:true});t.ensureReportId=ensureReportId;t.uploadTestRun=uploadTestRun;t.mapAttachmentsToTestResults=mapAttachmentsToTestResults;t.uploadArtifacts=uploadArtifacts;const o=r(406);const n="https://test-manager-backend.fly.dev";function ensureReportId(e){if(typeof e.reportId==="string"&&e.reportId.trim().length>0){return e.reportId}const t=crypto.randomUUID();e.reportId=t;return t}function resolveApiUrl(e){const t=normalizeApiUrl(e);if(t){return t}const r=getEnvApiUrl();if(r){return r}return n}function getEnvApiUrl(){if(typeof process==="undefined"||!process?.env){return undefined}return normalizeApiUrl(process.env.TESTREAM_API_URL)}function normalizeApiUrl(e){if(!e){return undefined}const t=e.trim();if(!t){return undefined}return t.replace(/\/+$/,"")}function isReportAlreadyExistsConflict(e){return e.errorCode==="report_already_exists"}function formatUploadError(e){const t=e.detail||e.title||e.rawBody||"Unknown error";const r=e.errorCode?`, code=${e.errorCode}`:"";return`Upload failed (HTTP ${e.statusCode}${r}): ${t}`}async function parseHttpError(e){const t=await e.text();const r=e.headers.get("content-type")||"";if(r.toLowerCase().includes("json")&&t.trim().length>0){try{const r=JSON.parse(t);return{statusCode:e.status,title:r.title,detail:r.detail||r.details||r.error,errorCode:r.errorCode,rawBody:t}}catch{}}return{statusCode:e.status,rawBody:t}}function resolveUploadContext(e){const t=(0,o.detectCIContext)();return{commitSha:e.commitSha??t.commitSha,branch:e.branch??t.branch,repositoryUrl:e.repositoryUrl??t.repositoryUrl,buildName:e.buildName,buildNumber:e.buildNumber??t.buildNumber,buildUrl:e.buildUrl??t.buildUrl,testEnvironment:e.testEnvironment,appName:e.appName,appVersion:e.appVersion,testType:e.testType}}async function uploadTestRun(e){const{report:t,apiKey:r}=e;const o=resolveApiUrl(e.apiUrl);const n=ensureReportId(t);const s=resolveUploadContext(e);const i={report:t,reportId:n,...s};console.log("Uploading test results...");let a;try{a=await fetch(`${o}/api/v1/ingest`,{method:"POST",headers:{"X-API-KEY":r,"Content-Type":"application/json"},body:JSON.stringify(i)})}catch(e){const t=e instanceof Error?e.message:String(e);const r=`Connection failed: ${t}`;console.error(r);return{success:false,reportId:n,error:r}}if(!a.ok){const e=await parseHttpError(a);if(a.status===409&&isReportAlreadyExistsConflict(e)){console.warn("Report already exists (workflow may have been re-run)");return{success:true,reportId:n,summary:{passed:t.results.summary.passed,failed:t.results.summary.failed,skipped:t.results.summary.skipped,total:t.results.summary.tests},alreadyExists:true,statusCode:e.statusCode,errorCode:e.errorCode}}const r=formatUploadError(e);console.error(r);return{success:false,reportId:n,error:r,statusCode:e.statusCode,errorCode:e.errorCode,errorDetail:e.detail||e.rawBody}}const c=await a.json();console.log(`✓ Test results uploaded successfully`);console.log(` Report ID: ${c.reportId}`);console.log(` Test Run ID: ${c.testRunId}`);console.log(` Tests: ${c.summary.passed}/${c.summary.total} passed`);return{success:true,reportId:c.reportId,testRunId:c.testRunId,summary:{passed:c.summary.passed,failed:c.summary.failed,skipped:c.summary.skipped,total:c.summary.total},testResults:c.testResults}}function mapAttachmentsToTestResults(e,t){const r=new Map;for(const e of t){const t=r.get(e.name)??[];t.push(e.id);r.set(e.name,t)}const o=[];for(const t of e){const e=r.get(t.name);const n=e?.shift();if(!t.attachments||t.attachments.length===0){continue}if(!n){console.warn(`Skipping artifact upload: could not match test result for "${t.name}"`);continue}o.push({testResultId:n,attachments:t.attachments})}return o}async function uploadArtifacts(e){const{reportId:t,apiKey:r,testResults:o}=e;const n=resolveApiUrl(e.apiUrl);let s=0;for(const e of o){for(const o of e.attachments){try{const i=await uploadSingleArtifact({testResultId:e.testResultId,attachment:o,reportId:t,apiKey:r,apiUrl:n});if(i)s++}catch(e){const t=e instanceof Error?e.message:String(e);console.error(`Failed to upload artifact ${o.name}: ${t}`)}}}if(s>0){console.log(`✓ Uploaded ${s} artifact(s)`)}return s}async function uploadSingleArtifact(e){const{testResultId:t,attachment:o,reportId:n,apiKey:s,apiUrl:i}=e;const a=await Promise.resolve().then(r.t.bind(r,943,23));const c=await Promise.resolve().then(r.t.bind(r,928,23));const l=c.resolve(o.path);try{await a.access(l)}catch{console.warn(`Artifact not found: ${c.basename(l)}`);return false}let u;let d;const p=c.basename(l);const f=o.contentType||"application/octet-stream";try{u=await a.readFile(l);d=u.byteLength}catch(e){const t=e instanceof Error?e.message:String(e);throw new Error(`Failed to read file: ${t}`)}try{return await uploadWithPresignedUrl({testResultId:t,reportId:n,apiKey:s,apiUrl:i,attachmentName:o.name,fileName:p,contentType:f,sizeBytes:d,fileBuffer:u})}catch(e){if(!(e instanceof LegacyUploadRequiredError)){throw e}return await uploadWithLegacyEndpoint({testResultId:t,attachmentName:o.name,reportId:n,apiKey:s,apiUrl:i,fileName:p,contentType:f,fileBuffer:u})}}class LegacyUploadRequiredError extends Error{constructor(){super("Legacy upload endpoint required")}}async function uploadWithPresignedUrl(e){const{testResultId:t,reportId:r,apiKey:o,apiUrl:n,attachmentName:s,fileName:i,contentType:a,sizeBytes:c,fileBuffer:l}=e;const u={testResultId:t,ctrfAttachmentName:s,fileName:i,contentType:a,sizeBytes:c};const d=await fetch(`${n}/api/v1/artifacts/${r}/upload-url`,{method:"POST",headers:{"X-API-KEY":o,"Content-Type":"application/json"},body:JSON.stringify(u)});if(shouldFallbackToLegacyUpload(d.status)){throw new LegacyUploadRequiredError}if(!d.ok){const e=await d.text();throw new Error(`Failed to create direct upload URL (HTTP ${d.status}): ${e}`)}const p=await d.json();const f={...p.requiredHeaders??{}};if(!hasHeaderIgnoreCase(f,"Content-Type")){f["Content-Type"]=a}const m=await fetch(p.uploadUrl,{method:"PUT",headers:f,body:l});if(!m.ok){const e=await m.text();throw new Error(`Direct artifact upload failed (HTTP ${m.status}): ${e}`)}const h={testResultId:t,ctrfAttachmentName:s,fileName:i,contentType:a,sizeBytes:c,storageKey:p.storageKey};const _=await fetch(`${n}/api/v1/artifacts/${r}/complete`,{method:"POST",headers:{"X-API-KEY":o,"Content-Type":"application/json"},body:JSON.stringify(h)});if(!_.ok){const e=await _.text();throw new Error(`Failed to finalize artifact upload (HTTP ${_.status}): ${e}`)}return true}async function uploadWithLegacyEndpoint(e){const{testResultId:t,attachmentName:r,reportId:o,apiKey:n,apiUrl:s,fileName:i,contentType:a,fileBuffer:c}=e;const l=new Blob([new Uint8Array(c)],{type:a});const u=new FormData;u.append("testResultId",t);u.append("ctrfAttachmentName",r);u.append("file",l,i);const d=await fetch(`${s}/api/v1/artifacts/${o}`,{method:"POST",headers:{"X-API-KEY":n},body:u});if(!d.ok){const e=await d.text();throw new Error(`Legacy artifact upload failed (HTTP ${d.status}): ${e}`)}return true}function shouldFallbackToLegacyUpload(e){return e===404||e===405||e===501}function hasHeaderIgnoreCase(e,t){const r=t.toLowerCase();return Object.keys(e).some((e=>e.toLowerCase()===r))}},943:e=>{e.exports=require("fs/promises")},928:e=>{e.exports=require("path")}};var t={};function __nccwpck_require__(r){var o=t[r];if(o!==undefined){return o.exports}var n=t[r]={exports:{}};var s=true;try{e[r].call(n.exports,n,n.exports,__nccwpck_require__);s=false}finally{if(s)delete t[r]}return n.exports}(()=>{var e=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;var t;__nccwpck_require__.t=function(r,o){if(o&1)r=this(r);if(o&8)return r;if(typeof r==="object"&&r){if(o&4&&r.__esModule)return r;if(o&16&&typeof r.then==="function")return r}var n=Object.create(null);__nccwpck_require__.r(n);var s={};t=t||[null,e({}),e([]),e(e)];for(var i=o&2&&r;typeof i=="object"&&!~t.indexOf(i);i=e(i)){Object.getOwnPropertyNames(i).forEach((e=>s[e]=()=>r[e]))}s["default"]=()=>r;__nccwpck_require__.d(n,s);return n}})();(()=>{__nccwpck_require__.d=(e,t)=>{for(var r in t){if(__nccwpck_require__.o(t,r)&&!__nccwpck_require__.o(e,r)){Object.defineProperty(e,r,{enumerable:true,get:t[r]})}}}})();(()=>{__nccwpck_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t)})();(()=>{__nccwpck_require__.r=e=>{if(typeof Symbol!=="undefined"&&Symbol.toStringTag){Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})}Object.defineProperty(e,"__esModule",{value:true})}})();if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var r={};__nccwpck_require__.r(r);__nccwpck_require__.d(r,{TestreamVitestReporter:()=>TestreamVitestReporter,default:()=>TestreamVitestReporter});var o=__nccwpck_require__(943);var n=__nccwpck_require__(928);var s=__nccwpck_require__(322);function mapStatus(e){switch(e){case"passed":return"passed";case"failed":return"failed";case"skipped":return"skipped";default:return"pending"}}function buildSuiteName(e){const t=[];let r=e.parent;while(r&&r.type==="suite"){t.unshift(r.name);r=r.parent}return t.join(" > ")}function collectTests(e){const t=[];for(const r of e){if(r.type==="test"){t.push(r)}else if(r.type==="suite"){t.push(...collectTests(r.children))}}return t}function buildCTRFReport(e,t,r){const o=Date.now();const n=[];const s=new Set;for(const o of e){const e=collectTests(o.children);for(const o of e){const e=o.result();const i=o.diagnostic();const a=e.state;const c=mapStatus(a);const l=Math.round(i?.duration??0);const u=i?.startTime??r;const d=u+l;const p=i?.retryCount??0;const f=i?.flaky??false;const m=buildSuiteName(o);if(m){s.add(m)}let h;let _;const b=e.errors;if(b&&b.length>0){const e=b[0];h=e.message;const t=e.stackTrace??e.stack;_=typeof t==="string"?t:undefined}const y={name:o.name,status:c,duration:l,start:u,stop:d,rawStatus:a,tags:[],type:t.testType||"unit",filePath:o.module.moduleId,retries:p,flaky:f,steps:[],suite:m||undefined,stdout:[],stderr:[],message:h,trace:_};n.push(y)}}const i={tests:n.length,passed:n.filter((e=>e.status==="passed")).length,failed:n.filter((e=>e.status==="failed")).length,skipped:n.filter((e=>e.status==="skipped")).length,pending:n.filter((e=>e.status==="pending")).length,other:n.filter((e=>e.status==="other")).length,suites:s.size,start:r,stop:o};const a={reportFormat:"CTRF",specVersion:"0.0.1",timestamp:new Date(r).toISOString(),generatedBy:"@testream/vitest-reporter",extra:{branch:t.branch,commitSha:t.commitSha},results:{tool:{name:"vitest"},summary:i,tests:n,environment:{...t.testEnvironment?{testEnvironment:t.testEnvironment}:{},...t.appName?{appName:t.appName}:{},...t.appVersion?{appVersion:t.appVersion}:{},...t.buildName?{buildName:t.buildName}:{},...t.buildNumber?{buildNumber:t.buildNumber}:{},...t.buildUrl?{buildUrl:t.buildUrl}:{}}}};return a}class ReportUploader{constructor(e){this.config={apiKey:e.apiKey,branch:e.branch,commitSha:e.commitSha,repositoryUrl:e.repositoryUrl,failOnUploadError:e.failOnUploadError??false,buildName:e.buildName,buildNumber:e.buildNumber,buildUrl:e.buildUrl,testEnvironment:e.testEnvironment,appName:e.appName,appVersion:e.appVersion,testType:e.testType}}async uploadReport(e){try{const t=await(0,s.uploadTestRun)({report:e,apiKey:this.config.apiKey,commitSha:this.config.commitSha,branch:this.config.branch,repositoryUrl:this.config.repositoryUrl,buildName:this.config.buildName,buildNumber:this.config.buildNumber,buildUrl:this.config.buildUrl,testEnvironment:this.config.testEnvironment,appName:this.config.appName,appVersion:this.config.appVersion,testType:this.config.testType});if(!t.success){if(this.config.failOnUploadError){throw new Error(t.error||"Upload failed")}return t}let r=0;if(!t.alreadyExists&&t.testRunId&&t.testResults){const o=(0,s.mapAttachmentsToTestResults)(e.results.tests,t.testResults);if(o.length>0){r=await(0,s.uploadArtifacts)({reportId:t.reportId,apiKey:this.config.apiKey,testResults:o})}}return{...t,artifactCount:r}}catch(t){const r=t instanceof Error?t.message:String(t);if(this.config.failOnUploadError){throw new Error(`Failed to upload report: ${r}`)}return{success:false,reportId:(0,s.ensureReportId)(e),error:r}}}}class TestreamVitestReporter{constructor(e){this.uploader=null;this.startTimestamp=0;if(!e.apiKey){throw new Error("TestreamVitestReporter: apiKey is required")}this.config={uploadEnabled:true,outputFile:"ctrf-report.json",outputDir:"ctrf",failOnUploadError:false,testType:"unit",...e};const t=(0,s.detectCIContext)();if(!this.config.branch&&t.branch){this.config.branch=t.branch}if(!this.config.commitSha&&t.commitSha){this.config.commitSha=t.commitSha}if(!this.config.repositoryUrl&&t.repositoryUrl){this.config.repositoryUrl=t.repositoryUrl}if(!this.config.buildNumber&&t.buildNumber){this.config.buildNumber=t.buildNumber}if(!this.config.buildUrl&&t.buildUrl){this.config.buildUrl=t.buildUrl}this.reportPath=n.join(this.config.outputDir,this.config.outputFile);if(this.config.uploadEnabled){this.uploader=new ReportUploader(this.config)}}onTestRunStart(e){this.startTimestamp=Date.now();console.log("");console.log("=".repeat(60));console.log("Vitest Testream Reporter");console.log("=".repeat(60));if(this.config.uploadEnabled){if(this.config.branch)console.log(`Branch: ${this.config.branch}`);if(this.config.commitSha)console.log(`Commit: ${this.config.commitSha.substring(0,7)}`);if(this.config.repositoryUrl)console.log(`Repository: ${this.config.repositoryUrl}`)}else{console.log("Upload: Disabled")}console.log(`Report: ${this.reportPath}`);console.log("=".repeat(60));console.log("")}async onTestRunEnd(e,t,r){const n=buildCTRFReport(e,this.config,this.startTimestamp);try{await o.mkdir(this.config.outputDir,{recursive:true});await o.writeFile(this.reportPath,JSON.stringify(n,null,2))}catch(e){const t=e instanceof Error?e.message:String(e);console.error(`Failed to write CTRF report: ${t}`)}if(!this.config.uploadEnabled||!this.uploader){console.log("");console.log("CTRF report generated");console.log(` ${this.reportPath}`);return}console.log("");console.log("=".repeat(60));console.log("Uploading Test Results");console.log("=".repeat(60));try{const e=await this.uploader.uploadReport(n);if(e.success){console.log("=".repeat(60));console.log("Upload Complete");console.log("=".repeat(60));console.log("")}else{console.error("Upload completed with errors");if(e.error){console.error(`Error: ${e.error}`)}if(e.errorCode){console.error(`Error code: ${e.errorCode}`)}console.error("")}}catch(e){const t=e instanceof Error?e.message:String(e);console.error("");console.error("=".repeat(60));console.error("Upload Failed");console.error("=".repeat(60));console.error(`Error: ${t}`);console.error("");if(this.config.failOnUploadError){throw e}}}}const i=null&&TestreamVitestReporter;module.exports=r})();
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/jira-test-manager/jira-test-manager/packages/vitest-reporter/src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAI/C;;GAEG;AACH,qBAAa,sBAAuB,YAAW,QAAQ;IACrD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAa;gBAEvB,MAAM,EAAE,oBAAoB;IAuCxC,cAAc,CAAC,eAAe,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAmBjE,YAAY,CAChB,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,EACtC,gBAAgB,EAAE,aAAa,CAAC,eAAe,CAAC,EAChD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC;CAoDjB;AAED,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/jira-test-manager/jira-test-manager/packages/vitest-reporter/src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAI/C;;GAEG;AACH,qBAAa,sBAAuB,YAAW,QAAQ;IACrD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAa;gBAEvB,MAAM,EAAE,oBAAoB;IAwCxC,cAAc,CAAC,eAAe,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAmBjE,YAAY,CAChB,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,EACtC,gBAAgB,EAAE,aAAa,CAAC,eAAe,CAAC,EAChD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC;CA0DjB;AAED,eAAe,sBAAsB,CAAC"}
@@ -1 +1 @@
1
- var W=Object.create;var v=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var Z=Object.getOwnPropertyNames;var ee=Object.getPrototypeOf,te=Object.prototype.hasOwnProperty;var b=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var re=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Z(t))!te.call(e,s)&&s!==r&&v(e,s,{get:()=>t[s],enumerable:!(o=Q(t,s))||o.enumerable});return e};var $=(e,t,r)=>(r=e!=null?W(ee(e)):{},re(t||!e||!e.__esModule?v(r,"default",{value:e,enumerable:!0}):r,e));var F=b(D=>{"use strict";Object.defineProperty(D,"__esModule",{value:!0})});var H=b(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.detectCIContext=se;function se(){let e=process.env;return e.GITHUB_ACTIONS==="true"?{branch:e.GITHUB_HEAD_REF||e.GITHUB_REF_NAME||e.GITHUB_REF?.replace("refs/heads/",""),commitSha:e.GITHUB_SHA,repositoryUrl:e.GITHUB_SERVER_URL&&e.GITHUB_REPOSITORY?`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}`:void 0,buildNumber:e.GITHUB_RUN_NUMBER,buildUrl:e.GITHUB_SERVER_URL&&e.GITHUB_REPOSITORY&&e.GITHUB_RUN_ID?`${e.GITHUB_SERVER_URL}/${e.GITHUB_REPOSITORY}/actions/runs/${e.GITHUB_RUN_ID}`:void 0}:e.GITLAB_CI==="true"?{branch:e.CI_COMMIT_BRANCH||e.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME,commitSha:e.CI_COMMIT_SHA,repositoryUrl:e.CI_PROJECT_URL,buildNumber:e.CI_PIPELINE_IID,buildUrl:e.CI_PIPELINE_URL}:e.TF_BUILD==="True"?{branch:e.BUILD_SOURCEBRANCH?.replace("refs/heads/",""),commitSha:e.BUILD_SOURCEVERSION,repositoryUrl:e.BUILD_REPOSITORY_URI,buildNumber:e.BUILD_BUILDNUMBER,buildUrl:e.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI&&e.SYSTEM_TEAMPROJECT&&e.BUILD_BUILDID?`${e.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${e.SYSTEM_TEAMPROJECT}/_build/results?buildId=${e.BUILD_BUILDID}`:void 0}:e.CIRCLECI==="true"?{branch:e.CIRCLE_BRANCH,commitSha:e.CIRCLE_SHA1,repositoryUrl:e.CIRCLE_REPOSITORY_URL,buildNumber:e.CIRCLE_BUILD_NUM,buildUrl:e.CIRCLE_BUILD_URL}:e.JENKINS_URL?{branch:e.GIT_BRANCH?.replace("origin/",""),commitSha:e.GIT_COMMIT,repositoryUrl:e.GIT_URL,buildNumber:e.BUILD_NUMBER,buildUrl:e.BUILD_URL}:e.BITBUCKET_BUILD_NUMBER?{branch:e.BITBUCKET_BRANCH,commitSha:e.BITBUCKET_COMMIT,repositoryUrl:e.BITBUCKET_GIT_HTTP_ORIGIN,buildNumber:e.BITBUCKET_BUILD_NUMBER,buildUrl:e.BITBUCKET_REPO_FULL_NAME&&e.BITBUCKET_BUILD_NUMBER?`https://bitbucket.org/${e.BITBUCKET_REPO_FULL_NAME}/pipelines/results/${e.BITBUCKET_BUILD_NUMBER}`:void 0}:{}}});var G=b(y=>{"use strict";Object.defineProperty(y,"__esModule",{value:!0});y.ensureReportId=K;y.uploadTestRun=ae;y.mapAttachmentsToTestResults=ie;y.uploadArtifacts=le;var oe="https://test-manager-backend.fly.dev";function K(e){if(typeof e.reportId=="string"&&e.reportId.trim().length>0)return e.reportId;let t=crypto.randomUUID();return e.reportId=t,t}function V(e){let t=x(e);if(t)return t;let r=ne();return r||oe}function ne(){if(!(typeof process>"u"||!process?.env))return x(process.env.TESTREAM_API_URL)}function x(e){if(!e)return;let t=e.trim();if(t)return t.replace(/\/+$/,"")}async function ae(e){let{report:t,apiKey:r}=e,o=V(e.apiUrl),s=K(t),a={report:t,reportId:s,commitSha:e.commitSha,branch:e.branch,repositoryUrl:e.repositoryUrl,buildName:e.buildName,buildNumber:e.buildNumber,buildUrl:e.buildUrl,testEnvironment:e.testEnvironment,appName:e.appName,appVersion:e.appVersion,testType:e.testType};console.log("Uploading test results...");let i;try{i=await fetch(`${o}/api/v1/ingest`,{method:"POST",headers:{"X-API-KEY":r,"Content-Type":"application/json"},body:JSON.stringify(a)})}catch(n){let d=n instanceof Error?n.message:String(n);return{success:!1,reportId:s,error:`Connection failed: ${d}`}}if(i.status===409)return console.warn("Report already exists (workflow may have been re-run)"),{success:!0,reportId:s,summary:{passed:t.results.summary.passed,failed:t.results.summary.failed,skipped:t.results.summary.skipped,total:t.results.summary.tests},alreadyExists:!0};if(!i.ok){let n=await i.text();return{success:!1,reportId:s,error:`Upload failed (HTTP ${i.status}): ${n}`}}let l=await i.json();return console.log("\u2713 Test results uploaded successfully"),console.log(` Report ID: ${l.reportId}`),console.log(` Test Run ID: ${l.testRunId}`),console.log(` Tests: ${l.summary.passed}/${l.summary.total} passed`),{success:!0,reportId:l.reportId,testRunId:l.testRunId,summary:{passed:l.summary.passed,failed:l.summary.failed,skipped:l.summary.skipped,total:l.summary.total},testResults:l.testResults}}function ie(e,t){let r=new Map;for(let s of t){let a=r.get(s.name)??[];a.push(s.id),r.set(s.name,a)}let o=[];for(let s of e){let i=r.get(s.name)?.shift();if(!(!s.attachments||s.attachments.length===0)){if(!i){console.warn(`Skipping artifact upload: could not match test result for "${s.name}"`);continue}o.push({testResultId:i,attachments:s.attachments})}}return o}async function le(e){let{reportId:t,apiKey:r,testResults:o}=e,s=V(e.apiUrl),a=0;for(let i of o)for(let l of i.attachments)try{await ue({testResultId:i.testResultId,attachment:l,reportId:t,apiKey:r,apiUrl:s})&&a++}catch(n){let d=n instanceof Error?n.message:String(n);console.error(`Failed to upload artifact ${l.name}: ${d}`)}return a>0&&console.log(`\u2713 Uploaded ${a} artifact(s)`),a}async function ue(e){let{testResultId:t,attachment:r,reportId:o,apiKey:s,apiUrl:a}=e,i=await import("fs/promises"),l=await import("path"),n=l.resolve(r.path);try{await i.access(n)}catch{return console.warn(`Artifact not found: ${l.basename(n)}`),!1}let d,c,p=l.basename(n),f=r.contentType||"application/octet-stream";try{d=await i.readFile(n),c=d.byteLength}catch(m){let T=m instanceof Error?m.message:String(m);throw new Error(`Failed to read file: ${T}`)}try{return await ce({testResultId:t,reportId:o,apiKey:s,apiUrl:a,attachmentName:r.name,fileName:p,contentType:f,sizeBytes:c,fileBuffer:d})}catch(m){if(!(m instanceof g))throw m;return await pe({testResultId:t,attachmentName:r.name,reportId:o,apiKey:s,apiUrl:a,fileName:p,contentType:f,fileBuffer:d})}}var g=class extends Error{constructor(){super("Legacy upload endpoint required")}};async function ce(e){let{testResultId:t,reportId:r,apiKey:o,apiUrl:s,attachmentName:a,fileName:i,contentType:l,sizeBytes:n,fileBuffer:d}=e,c={testResultId:t,ctrfAttachmentName:a,fileName:i,contentType:l,sizeBytes:n},p=await fetch(`${s}/api/v1/artifacts/${r}/upload-url`,{method:"POST",headers:{"X-API-KEY":o,"Content-Type":"application/json"},body:JSON.stringify(c)});if(de(p.status))throw new g;if(!p.ok){let R=await p.text();throw new Error(`Failed to create direct upload URL (HTTP ${p.status}): ${R}`)}let f=await p.json(),m={...f.requiredHeaders??{}};fe(m,"Content-Type")||(m["Content-Type"]=l);let T=await fetch(f.uploadUrl,{method:"PUT",headers:m,body:d});if(!T.ok){let R=await T.text();throw new Error(`Direct artifact upload failed (HTTP ${T.status}): ${R}`)}let I={testResultId:t,ctrfAttachmentName:a,fileName:i,contentType:l,sizeBytes:n,storageKey:f.storageKey},U=await fetch(`${s}/api/v1/artifacts/${r}/complete`,{method:"POST",headers:{"X-API-KEY":o,"Content-Type":"application/json"},body:JSON.stringify(I)});if(!U.ok){let R=await U.text();throw new Error(`Failed to finalize artifact upload (HTTP ${U.status}): ${R}`)}return!0}async function pe(e){let{testResultId:t,attachmentName:r,reportId:o,apiKey:s,apiUrl:a,fileName:i,contentType:l,fileBuffer:n}=e,d=new Blob([new Uint8Array(n)],{type:l}),c=new FormData;c.append("testResultId",t),c.append("ctrfAttachmentName",r),c.append("file",d,i);let p=await fetch(`${a}/api/v1/artifacts/${o}`,{method:"POST",headers:{"X-API-KEY":s},body:c});if(!p.ok){let f=await p.text();throw new Error(`Legacy artifact upload failed (HTTP ${p.status}): ${f}`)}return!0}function de(e){return e===404||e===405||e===501}function fe(e,t){let r=t.toLowerCase();return Object.keys(e).some(o=>o.toLowerCase()===r)}});var P=b(u=>{"use strict";var me=u&&u.__createBinding||(Object.create?function(e,t,r,o){o===void 0&&(o=r);var s=Object.getOwnPropertyDescriptor(t,r);(!s||("get"in s?!t.__esModule:s.writable||s.configurable))&&(s={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,o,s)}:function(e,t,r,o){o===void 0&&(o=r),e[o]=t[r]}),he=u&&u.__exportStar||function(e,t){for(var r in e)r!=="default"&&!Object.prototype.hasOwnProperty.call(t,r)&&me(t,e,r)};Object.defineProperty(u,"__esModule",{value:!0});u.ensureReportId=u.mapAttachmentsToTestResults=u.uploadArtifacts=u.uploadTestRun=u.detectCIContext=void 0;he(F(),u);var Te=H();Object.defineProperty(u,"detectCIContext",{enumerable:!0,get:function(){return Te.detectCIContext}});var E=G();Object.defineProperty(u,"uploadTestRun",{enumerable:!0,get:function(){return E.uploadTestRun}});Object.defineProperty(u,"uploadArtifacts",{enumerable:!0,get:function(){return E.uploadArtifacts}});Object.defineProperty(u,"mapAttachmentsToTestResults",{enumerable:!0,get:function(){return E.mapAttachmentsToTestResults}});Object.defineProperty(u,"ensureReportId",{enumerable:!0,get:function(){return E.ensureReportId}})});var q=$(P());import*as N from"fs/promises";import*as Y from"path";function Re(e){switch(e){case"passed":return"passed";case"failed":return"failed";case"skipped":return"skipped";default:return"pending"}}function Ue(e){let t=[],r=e.parent;for(;r&&r.type==="suite";)t.unshift(r.name),r=r.parent;return t.join(" > ")}function j(e){let t=[];for(let r of e)r.type==="test"?t.push(r):r.type==="suite"&&t.push(...j(r.children));return t}function k(e,t,r){let o=Date.now(),s=[],a=new Set;for(let n of e){let d=j(n.children);for(let c of d){let p=c.result(),f=c.diagnostic(),m=p.state,T=Re(m),I=Math.round(f?.duration??0),U=f?.startTime??r,R=U+I,J=f?.retryCount??0,z=f?.flaky??!1,S=Ue(c);S&&a.add(S);let A,L,B=p.errors;if(B&&B.length>0){let w=B[0];A=w.message;let M=w.stackTrace??w.stack;L=typeof M=="string"?M:void 0}let X={name:c.name,status:T,duration:I,start:U,stop:R,rawStatus:m,tags:[],type:t.testType||"unit",filePath:c.module.moduleId,retries:J,flaky:z,steps:[],suite:S||void 0,stdout:[],stderr:[],message:A,trace:L};s.push(X)}}let i={tests:s.length,passed:s.filter(n=>n.status==="passed").length,failed:s.filter(n=>n.status==="failed").length,skipped:s.filter(n=>n.status==="skipped").length,pending:s.filter(n=>n.status==="pending").length,other:s.filter(n=>n.status==="other").length,suites:a.size,start:r,stop:o};return{reportFormat:"CTRF",specVersion:"0.0.1",timestamp:new Date(r).toISOString(),generatedBy:"@testream/vitest-reporter",extra:{branch:t.branch,commitSha:t.commitSha},results:{tool:{name:"vitest"},summary:i,tests:s,environment:{...t.testEnvironment?{testEnvironment:t.testEnvironment}:{},...t.appName?{appName:t.appName}:{},...t.appVersion?{appVersion:t.appVersion}:{},...t.buildName?{buildName:t.buildName}:{},...t.buildNumber?{buildNumber:t.buildNumber}:{},...t.buildUrl?{buildUrl:t.buildUrl}:{}}}}}var h=$(P()),_=class{constructor(t){this.config={apiKey:t.apiKey,branch:t.branch,commitSha:t.commitSha,repositoryUrl:t.repositoryUrl,failOnUploadError:t.failOnUploadError??!1,buildName:t.buildName,buildNumber:t.buildNumber,buildUrl:t.buildUrl,testEnvironment:t.testEnvironment,appName:t.appName,appVersion:t.appVersion,testType:t.testType}}async uploadReport(t){try{let r=await(0,h.uploadTestRun)({report:t,apiKey:this.config.apiKey,commitSha:this.config.commitSha,branch:this.config.branch,repositoryUrl:this.config.repositoryUrl,buildName:this.config.buildName,buildNumber:this.config.buildNumber,buildUrl:this.config.buildUrl,testEnvironment:this.config.testEnvironment,appName:this.config.appName,appVersion:this.config.appVersion,testType:this.config.testType});if(!r.success){if(this.config.failOnUploadError)throw new Error(r.error||"Upload failed");return r}let o=0;if(!r.alreadyExists&&r.testRunId&&r.testResults){let s=(0,h.mapAttachmentsToTestResults)(t.results.tests,r.testResults);s.length>0&&(o=await(0,h.uploadArtifacts)({reportId:r.reportId,apiKey:this.config.apiKey,testResults:s}))}return{...r,artifactCount:o}}catch(r){let o=r instanceof Error?r.message:String(r);if(this.config.failOnUploadError)throw new Error(`Failed to upload report: ${o}`);return{success:!1,reportId:(0,h.ensureReportId)(t),error:o}}}};var C=class{constructor(t){this.uploader=null;this.startTimestamp=0;if(!t.apiKey)throw new Error("TestreamVitestReporter: apiKey is required");this.config={uploadEnabled:!0,outputFile:"ctrf-report.json",outputDir:"ctrf",failOnUploadError:!1,testType:"unit",...t};let r=(0,q.detectCIContext)();!this.config.branch&&r.branch&&(this.config.branch=r.branch),!this.config.commitSha&&r.commitSha&&(this.config.commitSha=r.commitSha),!this.config.repositoryUrl&&r.repositoryUrl&&(this.config.repositoryUrl=r.repositoryUrl),!this.config.buildNumber&&r.buildNumber&&(this.config.buildNumber=r.buildNumber),!this.config.buildUrl&&r.buildUrl&&(this.config.buildUrl=r.buildUrl),this.reportPath=Y.join(this.config.outputDir,this.config.outputFile),this.config.uploadEnabled&&(this.uploader=new _(this.config))}onTestRunStart(t){this.startTimestamp=Date.now(),console.log(""),console.log("=".repeat(60)),console.log("Vitest Testream Reporter"),console.log("=".repeat(60)),this.config.uploadEnabled?(this.config.branch&&console.log(`Branch: ${this.config.branch}`),this.config.commitSha&&console.log(`Commit: ${this.config.commitSha.substring(0,7)}`),this.config.repositoryUrl&&console.log(`Repository: ${this.config.repositoryUrl}`)):console.log("Upload: Disabled"),console.log(`Report: ${this.reportPath}`),console.log("=".repeat(60)),console.log("")}async onTestRunEnd(t,r,o){let s=k(t,this.config,this.startTimestamp);try{await N.mkdir(this.config.outputDir,{recursive:!0}),await N.writeFile(this.reportPath,JSON.stringify(s,null,2))}catch(a){let i=a instanceof Error?a.message:String(a);console.error(`Failed to write CTRF report: ${i}`)}if(!this.config.uploadEnabled||!this.uploader){console.log(""),console.log("CTRF report generated"),console.log(` ${this.reportPath}`);return}console.log(""),console.log("=".repeat(60)),console.log("Uploading Test Results"),console.log("=".repeat(60));try{(await this.uploader.uploadReport(s)).success?(console.log("=".repeat(60)),console.log("Upload Complete"),console.log("=".repeat(60)),console.log("")):(console.error("Upload completed with errors"),console.error(""))}catch(a){let i=a instanceof Error?a.message:String(a);if(console.error(""),console.error("=".repeat(60)),console.error("Upload Failed"),console.error("=".repeat(60)),console.error(`Error: ${i}`),console.error(""),this.config.failOnUploadError)throw a}}};export{C as TestreamVitestReporter,C as default};
1
+ var Q=Object.create;var H=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var et=Object.getPrototypeOf,rt=Object.prototype.hasOwnProperty;var I=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ot=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of tt(e))!rt.call(t,o)&&o!==r&&H(t,o,{get:()=>e[o],enumerable:!(s=Z(e,o))||s.enumerable});return t};var x=(t,e,r)=>(r=t!=null?Q(et(t)):{},ot(e||!t||!t.__esModule?H(r,"default",{value:t,enumerable:!0}):r,t));var G=I(F=>{"use strict";Object.defineProperty(F,"__esModule",{value:!0})});var A=I(P=>{"use strict";Object.defineProperty(P,"__esModule",{value:!0});P.detectCIContext=ht;function O(t,e){if(t)return t.startsWith(e)?t.slice(e.length):t}function st(){return globalThis.process?.env??{}}function it(t){if(!(!t.GITHUB_SERVER_URL||!t.GITHUB_REPOSITORY))return`${t.GITHUB_SERVER_URL}/${t.GITHUB_REPOSITORY}`}function nt(t){if(!(!t.GITHUB_SERVER_URL||!t.GITHUB_REPOSITORY||!t.GITHUB_RUN_ID))return`${t.GITHUB_SERVER_URL}/${t.GITHUB_REPOSITORY}/actions/runs/${t.GITHUB_RUN_ID}`}function at(t){if(t.GITHUB_HEAD_REF)return t.GITHUB_HEAD_REF;if(t.GITHUB_REF?.startsWith("refs/heads/"))return t.GITHUB_REF_NAME??O(t.GITHUB_REF,"refs/heads/")}function ct(t){return{branch:at(t),commitSha:t.GITHUB_SHA,repositoryUrl:it(t),buildNumber:t.GITHUB_RUN_NUMBER,buildUrl:nt(t)}}function lt(t){return{branch:t.CI_COMMIT_BRANCH||t.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME,commitSha:t.CI_COMMIT_SHA,repositoryUrl:t.CI_PROJECT_URL,buildNumber:t.CI_PIPELINE_IID,buildUrl:t.CI_PIPELINE_URL}}function ut(t){return{branch:O(t.BUILD_SOURCEBRANCH,"refs/heads/"),commitSha:t.BUILD_SOURCEVERSION,repositoryUrl:t.BUILD_REPOSITORY_URI,buildNumber:t.BUILD_BUILDNUMBER,buildUrl:t.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI&&t.SYSTEM_TEAMPROJECT&&t.BUILD_BUILDID?`${t.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${t.SYSTEM_TEAMPROJECT}/_build/results?buildId=${t.BUILD_BUILDID}`:void 0}}function dt(t){return{branch:t.CIRCLE_BRANCH,commitSha:t.CIRCLE_SHA1,repositoryUrl:t.CIRCLE_REPOSITORY_URL,buildNumber:t.CIRCLE_BUILD_NUM,buildUrl:t.CIRCLE_BUILD_URL}}function pt(t){return{branch:O(t.GIT_BRANCH,"origin/"),commitSha:t.GIT_COMMIT,repositoryUrl:t.GIT_URL,buildNumber:t.BUILD_NUMBER,buildUrl:t.BUILD_URL}}function ft(t){return{branch:t.BITBUCKET_BRANCH,commitSha:t.BITBUCKET_COMMIT,repositoryUrl:t.BITBUCKET_GIT_HTTP_ORIGIN,buildNumber:t.BITBUCKET_BUILD_NUMBER,buildUrl:t.BITBUCKET_REPO_FULL_NAME&&t.BITBUCKET_BUILD_NUMBER?`https://bitbucket.org/${t.BITBUCKET_REPO_FULL_NAME}/pipelines/results/${t.BITBUCKET_BUILD_NUMBER}`:void 0}}var mt=[{isMatch:t=>t.GITHUB_ACTIONS==="true",detect:ct},{isMatch:t=>t.GITLAB_CI==="true",detect:lt},{isMatch:t=>t.TF_BUILD==="True",detect:ut},{isMatch:t=>t.CIRCLECI==="true",detect:dt},{isMatch:t=>!!t.JENKINS_URL,detect:pt},{isMatch:t=>!!t.BITBUCKET_BUILD_NUMBER,detect:ft}];function ht(){let t=st();for(let e of mt)if(e.isMatch(t))return e.detect(t);return{}}});var k=I(U=>{"use strict";Object.defineProperty(U,"__esModule",{value:!0});U.ensureReportId=K;U.uploadTestRun=Et;U.mapAttachmentsToTestResults=Ct;U.uploadArtifacts=_t;var Tt=A(),Rt="https://test-manager-backend.fly.dev";function K(t){if(typeof t.reportId=="string"&&t.reportId.trim().length>0)return t.reportId;let e=crypto.randomUUID();return t.reportId=e,e}function V(t){let e=j(t);if(e)return e;let r=yt();return r||Rt}function yt(){if(!(typeof process>"u"||!process?.env))return j(process.env.TESTREAM_API_URL)}function j(t){if(!t)return;let e=t.trim();if(e)return e.replace(/\/+$/,"")}function Ut(t){return t.errorCode==="report_already_exists"}function bt(t){let e=t.detail||t.title||t.rawBody||"Unknown error",r=t.errorCode?`, code=${t.errorCode}`:"";return`Upload failed (HTTP ${t.statusCode}${r}): ${e}`}async function It(t){let e=await t.text();if((t.headers.get("content-type")||"").toLowerCase().includes("json")&&e.trim().length>0)try{let s=JSON.parse(e);return{statusCode:t.status,title:s.title,detail:s.detail||s.details||s.error,errorCode:s.errorCode,rawBody:e}}catch{}return{statusCode:t.status,rawBody:e}}function gt(t){let e=(0,Tt.detectCIContext)();return{commitSha:t.commitSha??e.commitSha,branch:t.branch??e.branch,repositoryUrl:t.repositoryUrl??e.repositoryUrl,buildName:t.buildName,buildNumber:t.buildNumber??e.buildNumber,buildUrl:t.buildUrl??e.buildUrl,testEnvironment:t.testEnvironment,appName:t.appName,appVersion:t.appVersion,testType:t.testType}}async function Et(t){let{report:e,apiKey:r}=t,s=V(t.apiUrl),o=K(e),n=gt(t),c={report:e,reportId:o,...n};console.log("Uploading test results...");let l;try{l=await fetch(`${s}/api/v1/ingest`,{method:"POST",headers:{"X-API-KEY":r,"Content-Type":"application/json"},body:JSON.stringify(c)})}catch(a){let d=`Connection failed: ${a instanceof Error?a.message:String(a)}`;return console.error(d),{success:!1,reportId:o,error:d}}if(!l.ok){let a=await It(l);if(l.status===409&&Ut(a))return console.warn("Report already exists (workflow may have been re-run)"),{success:!0,reportId:o,summary:{passed:e.results.summary.passed,failed:e.results.summary.failed,skipped:e.results.summary.skipped,total:e.results.summary.tests},alreadyExists:!0,statusCode:a.statusCode,errorCode:a.errorCode};let u=bt(a);return console.error(u),{success:!1,reportId:o,error:u,statusCode:a.statusCode,errorCode:a.errorCode,errorDetail:a.detail||a.rawBody}}let i=await l.json();return console.log("\u2713 Test results uploaded successfully"),console.log(` Report ID: ${i.reportId}`),console.log(` Test Run ID: ${i.testRunId}`),console.log(` Tests: ${i.summary.passed}/${i.summary.total} passed`),{success:!0,reportId:i.reportId,testRunId:i.testRunId,summary:{passed:i.summary.passed,failed:i.summary.failed,skipped:i.summary.skipped,total:i.summary.total},testResults:i.testResults}}function Ct(t,e){let r=new Map;for(let o of e){let n=r.get(o.name)??[];n.push(o.id),r.set(o.name,n)}let s=[];for(let o of t){let c=r.get(o.name)?.shift();if(!(!o.attachments||o.attachments.length===0)){if(!c){console.warn(`Skipping artifact upload: could not match test result for "${o.name}"`);continue}s.push({testResultId:c,attachments:o.attachments})}}return s}async function _t(t){let{reportId:e,apiKey:r,testResults:s}=t,o=V(t.apiUrl),n=0;for(let c of s)for(let l of c.attachments)try{await Nt({testResultId:c.testResultId,attachment:l,reportId:e,apiKey:r,apiUrl:o})&&n++}catch(i){let a=i instanceof Error?i.message:String(i);console.error(`Failed to upload artifact ${l.name}: ${a}`)}return n>0&&console.log(`\u2713 Uploaded ${n} artifact(s)`),n}async function Nt(t){let{testResultId:e,attachment:r,reportId:s,apiKey:o,apiUrl:n}=t,c=await import("fs/promises"),l=await import("path"),i=l.resolve(r.path);try{await c.access(i)}catch{return console.warn(`Artifact not found: ${l.basename(i)}`),!1}let a,u,d=l.basename(i),f=r.contentType||"application/octet-stream";try{a=await c.readFile(i),u=a.byteLength}catch(m){let T=m instanceof Error?m.message:String(m);throw new Error(`Failed to read file: ${T}`)}try{return await Bt({testResultId:e,reportId:s,apiKey:o,apiUrl:n,attachmentName:r.name,fileName:d,contentType:f,sizeBytes:u,fileBuffer:a})}catch(m){if(!(m instanceof g))throw m;return await St({testResultId:e,attachmentName:r.name,reportId:s,apiKey:o,apiUrl:n,fileName:d,contentType:f,fileBuffer:a})}}var g=class extends Error{constructor(){super("Legacy upload endpoint required")}};async function Bt(t){let{testResultId:e,reportId:r,apiKey:s,apiUrl:o,attachmentName:n,fileName:c,contentType:l,sizeBytes:i,fileBuffer:a}=t,u={testResultId:e,ctrfAttachmentName:n,fileName:c,contentType:l,sizeBytes:i},d=await fetch(`${o}/api/v1/artifacts/${r}/upload-url`,{method:"POST",headers:{"X-API-KEY":s,"Content-Type":"application/json"},body:JSON.stringify(u)});if(wt(d.status))throw new g;if(!d.ok){let R=await d.text();throw new Error(`Failed to create direct upload URL (HTTP ${d.status}): ${R}`)}let f=await d.json(),m={...f.requiredHeaders??{}};Ot(m,"Content-Type")||(m["Content-Type"]=l);let T=await fetch(f.uploadUrl,{method:"PUT",headers:m,body:a});if(!T.ok){let R=await T.text();throw new Error(`Direct artifact upload failed (HTTP ${T.status}): ${R}`)}let b={testResultId:e,ctrfAttachmentName:n,fileName:c,contentType:l,sizeBytes:i,storageKey:f.storageKey},y=await fetch(`${o}/api/v1/artifacts/${r}/complete`,{method:"POST",headers:{"X-API-KEY":s,"Content-Type":"application/json"},body:JSON.stringify(b)});if(!y.ok){let R=await y.text();throw new Error(`Failed to finalize artifact upload (HTTP ${y.status}): ${R}`)}return!0}async function St(t){let{testResultId:e,attachmentName:r,reportId:s,apiKey:o,apiUrl:n,fileName:c,contentType:l,fileBuffer:i}=t,a=new Blob([new Uint8Array(i)],{type:l}),u=new FormData;u.append("testResultId",e),u.append("ctrfAttachmentName",r),u.append("file",a,c);let d=await fetch(`${n}/api/v1/artifacts/${s}`,{method:"POST",headers:{"X-API-KEY":o},body:u});if(!d.ok){let f=await d.text();throw new Error(`Legacy artifact upload failed (HTTP ${d.status}): ${f}`)}return!0}function wt(t){return t===404||t===405||t===501}function Ot(t,e){let r=e.toLowerCase();return Object.keys(t).some(s=>s.toLowerCase()===r)}});var L=I(p=>{"use strict";var Pt=p&&p.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r);var o=Object.getOwnPropertyDescriptor(e,r);(!o||("get"in o?!e.__esModule:o.writable||o.configurable))&&(o={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,s,o)}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),At=p&&p.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&Pt(e,t,r)};Object.defineProperty(p,"__esModule",{value:!0});p.ensureReportId=p.mapAttachmentsToTestResults=p.uploadArtifacts=p.uploadTestRun=p.detectCIContext=void 0;At(G(),p);var Lt=A();Object.defineProperty(p,"detectCIContext",{enumerable:!0,get:function(){return Lt.detectCIContext}});var E=k();Object.defineProperty(p,"uploadTestRun",{enumerable:!0,get:function(){return E.uploadTestRun}});Object.defineProperty(p,"uploadArtifacts",{enumerable:!0,get:function(){return E.uploadArtifacts}});Object.defineProperty(p,"mapAttachmentsToTestResults",{enumerable:!0,get:function(){return E.mapAttachmentsToTestResults}});Object.defineProperty(p,"ensureReportId",{enumerable:!0,get:function(){return E.ensureReportId}})});var z=x(L());import*as N from"fs/promises";import*as J from"path";function Mt(t){switch(t){case"passed":return"passed";case"failed":return"failed";case"skipped":return"skipped";default:return"pending"}}function $t(t){let e=[],r=t.parent;for(;r&&r.type==="suite";)e.unshift(r.name),r=r.parent;return e.join(" > ")}function Y(t){let e=[];for(let r of t)r.type==="test"?e.push(r):r.type==="suite"&&e.push(...Y(r.children));return e}function q(t,e,r){let s=Date.now(),o=[],n=new Set;for(let i of t){let a=Y(i.children);for(let u of a){let d=u.result(),f=u.diagnostic(),m=d.state,T=Mt(m),b=Math.round(f?.duration??0),y=f?.startTime??r,R=y+b,W=f?.retryCount??0,X=f?.flaky??!1,B=$t(u);B&&n.add(B);let M,$,S=d.errors;if(S&&S.length>0){let w=S[0];M=w.message;let D=w.stackTrace??w.stack;$=typeof D=="string"?D:void 0}let v={name:u.name,status:T,duration:b,start:y,stop:R,rawStatus:m,tags:[],type:e.testType||"unit",filePath:u.module.moduleId,retries:W,flaky:X,steps:[],suite:B||void 0,stdout:[],stderr:[],message:M,trace:$};o.push(v)}}let c={tests:o.length,passed:o.filter(i=>i.status==="passed").length,failed:o.filter(i=>i.status==="failed").length,skipped:o.filter(i=>i.status==="skipped").length,pending:o.filter(i=>i.status==="pending").length,other:o.filter(i=>i.status==="other").length,suites:n.size,start:r,stop:s};return{reportFormat:"CTRF",specVersion:"0.0.1",timestamp:new Date(r).toISOString(),generatedBy:"@testream/vitest-reporter",extra:{branch:e.branch,commitSha:e.commitSha},results:{tool:{name:"vitest"},summary:c,tests:o,environment:{...e.testEnvironment?{testEnvironment:e.testEnvironment}:{},...e.appName?{appName:e.appName}:{},...e.appVersion?{appVersion:e.appVersion}:{},...e.buildName?{buildName:e.buildName}:{},...e.buildNumber?{buildNumber:e.buildNumber}:{},...e.buildUrl?{buildUrl:e.buildUrl}:{}}}}}var h=x(L()),C=class{constructor(e){this.config={apiKey:e.apiKey,branch:e.branch,commitSha:e.commitSha,repositoryUrl:e.repositoryUrl,failOnUploadError:e.failOnUploadError??!1,buildName:e.buildName,buildNumber:e.buildNumber,buildUrl:e.buildUrl,testEnvironment:e.testEnvironment,appName:e.appName,appVersion:e.appVersion,testType:e.testType}}async uploadReport(e){try{let r=await(0,h.uploadTestRun)({report:e,apiKey:this.config.apiKey,commitSha:this.config.commitSha,branch:this.config.branch,repositoryUrl:this.config.repositoryUrl,buildName:this.config.buildName,buildNumber:this.config.buildNumber,buildUrl:this.config.buildUrl,testEnvironment:this.config.testEnvironment,appName:this.config.appName,appVersion:this.config.appVersion,testType:this.config.testType});if(!r.success){if(this.config.failOnUploadError)throw new Error(r.error||"Upload failed");return r}let s=0;if(!r.alreadyExists&&r.testRunId&&r.testResults){let o=(0,h.mapAttachmentsToTestResults)(e.results.tests,r.testResults);o.length>0&&(s=await(0,h.uploadArtifacts)({reportId:r.reportId,apiKey:this.config.apiKey,testResults:o}))}return{...r,artifactCount:s}}catch(r){let s=r instanceof Error?r.message:String(r);if(this.config.failOnUploadError)throw new Error(`Failed to upload report: ${s}`);return{success:!1,reportId:(0,h.ensureReportId)(e),error:s}}}};var _=class{constructor(e){this.uploader=null;this.startTimestamp=0;if(!e.apiKey)throw new Error("TestreamVitestReporter: apiKey is required");this.config={uploadEnabled:!0,outputFile:"ctrf-report.json",outputDir:"ctrf",failOnUploadError:!1,testType:"unit",...e};let r=(0,z.detectCIContext)();!this.config.branch&&r.branch&&(this.config.branch=r.branch),!this.config.commitSha&&r.commitSha&&(this.config.commitSha=r.commitSha),!this.config.repositoryUrl&&r.repositoryUrl&&(this.config.repositoryUrl=r.repositoryUrl),!this.config.buildNumber&&r.buildNumber&&(this.config.buildNumber=r.buildNumber),!this.config.buildUrl&&r.buildUrl&&(this.config.buildUrl=r.buildUrl),this.reportPath=J.join(this.config.outputDir,this.config.outputFile),this.config.uploadEnabled&&(this.uploader=new C(this.config))}onTestRunStart(e){this.startTimestamp=Date.now(),console.log(""),console.log("=".repeat(60)),console.log("Vitest Testream Reporter"),console.log("=".repeat(60)),this.config.uploadEnabled?(this.config.branch&&console.log(`Branch: ${this.config.branch}`),this.config.commitSha&&console.log(`Commit: ${this.config.commitSha.substring(0,7)}`),this.config.repositoryUrl&&console.log(`Repository: ${this.config.repositoryUrl}`)):console.log("Upload: Disabled"),console.log(`Report: ${this.reportPath}`),console.log("=".repeat(60)),console.log("")}async onTestRunEnd(e,r,s){let o=q(e,this.config,this.startTimestamp);try{await N.mkdir(this.config.outputDir,{recursive:!0}),await N.writeFile(this.reportPath,JSON.stringify(o,null,2))}catch(n){let c=n instanceof Error?n.message:String(n);console.error(`Failed to write CTRF report: ${c}`)}if(!this.config.uploadEnabled||!this.uploader){console.log(""),console.log("CTRF report generated"),console.log(` ${this.reportPath}`);return}console.log(""),console.log("=".repeat(60)),console.log("Uploading Test Results"),console.log("=".repeat(60));try{let n=await this.uploader.uploadReport(o);n.success?(console.log("=".repeat(60)),console.log("Upload Complete"),console.log("=".repeat(60)),console.log("")):(console.error("Upload completed with errors"),n.error&&console.error(`Error: ${n.error}`),n.errorCode&&console.error(`Error code: ${n.errorCode}`),console.error(""))}catch(n){let c=n instanceof Error?n.message:String(n);if(console.error(""),console.error("=".repeat(60)),console.error("Upload Failed"),console.error("=".repeat(60)),console.error(`Error: ${c}`),console.error(""),this.config.failOnUploadError)throw n}}};export{_ as TestreamVitestReporter,_ as default};
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAI/C;;GAEG;AACH,qBAAa,sBAAuB,YAAW,QAAQ;IACrD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAa;gBAEvB,MAAM,EAAE,oBAAoB;IAuCxC,cAAc,CAAC,eAAe,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAmBjE,YAAY,CAChB,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,EACtC,gBAAgB,EAAE,aAAa,CAAC,eAAe,CAAC,EAChD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC;CAoDjB;AAED,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAI/C;;GAEG;AACH,qBAAa,sBAAuB,YAAW,QAAQ;IACrD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAa;gBAEvB,MAAM,EAAE,oBAAoB;IAwCxC,cAAc,CAAC,eAAe,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAmBjE,YAAY,CAChB,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,EACtC,gBAAgB,EAAE,aAAa,CAAC,eAAe,CAAC,EAChD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC;CA0DjB;AAED,eAAe,sBAAsB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testream/vitest-reporter",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Vitest reporter to upload test results to Testream",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.mjs",