From aee6efd79321b5fb10d8988da4fbf8c22e18c964 Mon Sep 17 00:00:00 2001 From: mibali Date: Wed, 27 May 2026 16:58:46 +0100 Subject: [PATCH] fix: restore branch-only regressions safely --- extension-ready/popup.js | 4 +++- shared/role-profile-service.js | 35 ++++++++++++++++++++++++++++++ tests/popup-stats-ui.test.js | 22 +++++++++++++++++++ tests/role-profile-service.test.js | 7 ++++++ 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/extension-ready/popup.js b/extension-ready/popup.js index 5e66a98..c93689d 100644 --- a/extension-ready/popup.js +++ b/extension-ready/popup.js @@ -1041,7 +1041,9 @@ document.addEventListener('DOMContentLoaded', async () => { const li = text.match(/(?:https?:\/\/)?(?:www\.)?linkedin\.com\/in\/[\w-]+\/?/i); const gh = text.match(/(?:https?:\/\/)?(?:www\.)?github\.com\/[\w-]+\/?/i); const tw = text.match(/(?:https?:\/\/)?(?:www\.)?(?:twitter|x)\.com\/[\w-]+\/?/i); - const web = text.match(/\b(?:https?:\/\/|www\.)(?!(?:www\.)?(?:linkedin|github|twitter|x)\.com\b)[\w.-]+\.[a-z]{2,}(?:\/[\w./-]*)?/i); + const web = text.match( + /(? data service reliability', 'analytics/reporting -> dataset quality improvement', 'platform engineering -> workflow orchestration and observability'], + skillCategories: [ + { label: 'Pipelines & Orchestration', skills: ['ETL/ELT', 'Batch Pipelines', 'Streaming Basics', 'Workflow Orchestration'] }, + { label: 'Data Modelling & Warehousing', skills: ['Dimensional Modelling', 'Schema Design', 'Data Warehousing', 'Performance Tuning'] }, + { label: 'Quality & Reliability', skills: ['Data Quality Checks', 'Testing', 'Monitoring', 'Incident Response'] }, + { label: 'SQL & Storage', skills: ['SQL', 'PostgreSQL', 'Snowflake', 'BigQuery', 'Redshift'] }, + { label: 'Automation & Governance', skills: ['Automation', 'Documentation', 'Lineage Basics', 'Access Controls Basics'] }, + ], + positioning: 'Position the CV around reliable data pipelines, data modelling, warehouse performance, data quality, and dependable datasets for stakeholders. Avoid data strategy/governance ownership claims unless explicitly proven.', + }, { id: 'customer_success', family: 'Customer Success / Support', diff --git a/tests/popup-stats-ui.test.js b/tests/popup-stats-ui.test.js index af78e74..ac8fd82 100644 --- a/tests/popup-stats-ui.test.js +++ b/tests/popup-stats-ui.test.js @@ -1,4 +1,5 @@ import fs from 'node:fs'; +import vm from 'node:vm'; import { describe, expect, it } from 'vitest'; const popupHtml = fs.readFileSync(new URL('../extension-ready/popup.html', import.meta.url), 'utf8'); @@ -7,6 +8,14 @@ const contentJs = fs.readFileSync(new URL('../extension-ready/content.js', impor const contentCss = fs.readFileSync(new URL('../extension-ready/content.css', import.meta.url), 'utf8'); const backgroundJs = fs.readFileSync(new URL('../extension-ready/background.js', import.meta.url), 'utf8'); +function loadExtractCvContactUrls() { + const match = popupJs.match(/function extractCvContactUrls\(text\) \{[\s\S]*?\n \}/); + if (!match) throw new Error('extractCvContactUrls not found'); + const sandbox = {}; + vm.runInNewContext(`${match[0]}\nglobalThis.__extractCvContactUrls = extractCvContactUrls;`, sandbox); + return sandbox.__extractCvContactUrls; +} + describe('popup productivity stats UI', () => { it('renders the empty collapsed state', () => { expect(popupHtml).toContain('id="stats-summary">No activity yet'); @@ -90,4 +99,17 @@ describe('popup productivity stats UI', () => { expect(contentJs).toContain('labelTextWithoutControls'); expect(contentJs).toContain("field.closest?.('label')"); }); + + it('extracts bare portfolio domains without treating emails as websites', () => { + const extractCvContactUrls = loadExtractCvContactUrls(); + const urls = extractCvContactUrls(`Jane Doe +jane@example.xyz +linkedin.com/in/janedoe +github.com/janedoe +portfolio.xyz/work`); + + expect(urls.linkedin).toBe('https://linkedin.com/in/janedoe'); + expect(urls.github).toBe('https://github.com/janedoe'); + expect(urls.website).toBe('https://portfolio.xyz/work'); + }); }); diff --git a/tests/role-profile-service.test.js b/tests/role-profile-service.test.js index 4e81309..4d490c9 100644 --- a/tests/role-profile-service.test.js +++ b/tests/role-profile-service.test.js @@ -24,6 +24,13 @@ describe('RoleProfileService', () => { expect(service.classify({ jobTitle: 'Healthcare Administrator' })?.id).toBe('healthcare_admin'); }); + it('classifies data-engineering job titles into the data engineering role profile', () => { + expect(service.classify({ jobTitle: 'Data Engineer' })?.id).toBe('data_engineer'); + expect(service.classify({ jobTitle: 'Database Architect' })?.id).toBe('data_engineer'); + expect(service.classify({ jobTitle: 'ETL Developer' })?.id).toBe('data_engineer'); + expect(service.enrichJDData({ jobTitle: 'Data Engineer' }).domain).toBe('data_engineering'); + }); + it('enriches parsed JD data with positioning, credibility signals, risks, and skill categories', () => { const enriched = service.enrichJDData({ jobTitle: 'Product Manager',