chore(test): e2e test improvements:
- Link checker should report the first broken link - Link checker should only test external links if the domains are in the allowed list - If test subjects don't start with 'content/', treat them as URL paths and don't send them to map-files-to-urls.js.pull/6075/head
parent
02e10068ad
commit
da767f5228
|
@ -4,6 +4,7 @@ import * as fs from 'fs';
|
|||
import * as yaml from 'js-yaml';
|
||||
import {
|
||||
BROKEN_LINKS_FILE,
|
||||
FIRST_BROKEN_LINK_FILE,
|
||||
initializeReport,
|
||||
readBrokenLinksReport,
|
||||
} from './cypress/support/link-reporter.js';
|
||||
|
@ -90,8 +91,23 @@ export default defineConfig({
|
|||
return initializeReport();
|
||||
},
|
||||
|
||||
// Special case domains are now handled directly in the test without additional reporting
|
||||
// This task is kept for backward compatibility but doesn't do anything special
|
||||
reportSpecialCaseLink(linkData) {
|
||||
console.log(
|
||||
`✅ Expected status code: ${linkData.url} (status: ${linkData.status}) is valid for this domain`
|
||||
);
|
||||
return true;
|
||||
},
|
||||
|
||||
reportBrokenLink(linkData) {
|
||||
try {
|
||||
// Validate link data
|
||||
if (!linkData || !linkData.url || !linkData.page) {
|
||||
console.error('Invalid link data provided');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read current report
|
||||
const report = readBrokenLinksReport();
|
||||
|
||||
|
@ -102,29 +118,63 @@ export default defineConfig({
|
|||
report.push(pageReport);
|
||||
}
|
||||
|
||||
// Add the broken link to the page's report
|
||||
pageReport.links.push({
|
||||
url: linkData.url,
|
||||
status: linkData.status,
|
||||
type: linkData.type,
|
||||
linkText: linkData.linkText,
|
||||
});
|
||||
|
||||
// Write updated report back to file
|
||||
fs.writeFileSync(
|
||||
BROKEN_LINKS_FILE,
|
||||
JSON.stringify(report, null, 2)
|
||||
// Check if link is already in the report to avoid duplicates
|
||||
const isDuplicate = pageReport.links.some(
|
||||
(link) => link.url === linkData.url && link.type === linkData.type
|
||||
);
|
||||
|
||||
// Log the broken link immediately to console
|
||||
console.error(
|
||||
`❌ BROKEN LINK: ${linkData.url} (${linkData.status}) - ${linkData.type} on page ${linkData.page}`
|
||||
);
|
||||
if (!isDuplicate) {
|
||||
// Add the broken link to the page's report
|
||||
pageReport.links.push({
|
||||
url: linkData.url,
|
||||
status: linkData.status,
|
||||
type: linkData.type,
|
||||
linkText: linkData.linkText,
|
||||
});
|
||||
|
||||
// Write updated report back to file
|
||||
fs.writeFileSync(
|
||||
BROKEN_LINKS_FILE,
|
||||
JSON.stringify(report, null, 2)
|
||||
);
|
||||
|
||||
// Store first broken link if not already recorded
|
||||
const firstBrokenLinkExists =
|
||||
fs.existsSync(FIRST_BROKEN_LINK_FILE) &&
|
||||
fs.readFileSync(FIRST_BROKEN_LINK_FILE, 'utf8').trim() !== '';
|
||||
|
||||
if (!firstBrokenLinkExists) {
|
||||
// Store first broken link with complete information
|
||||
const firstBrokenLink = {
|
||||
url: linkData.url,
|
||||
status: linkData.status,
|
||||
type: linkData.type,
|
||||
linkText: linkData.linkText,
|
||||
page: linkData.page,
|
||||
time: new Date().toISOString(),
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
FIRST_BROKEN_LINK_FILE,
|
||||
JSON.stringify(firstBrokenLink, null, 2)
|
||||
);
|
||||
|
||||
console.error(
|
||||
`🔴 FIRST BROKEN LINK: ${linkData.url} (${linkData.status}) - ${linkData.type} on page ${linkData.page}`
|
||||
);
|
||||
}
|
||||
|
||||
// Log the broken link immediately to console
|
||||
console.error(
|
||||
`❌ BROKEN LINK: ${linkData.url} (${linkData.status}) - ${linkData.type} on page ${linkData.page}`
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Error reporting broken link: ${error.message}`);
|
||||
return false;
|
||||
// Even if there's an error, we want to ensure the test knows there was a broken link
|
||||
return true;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -5,6 +5,12 @@ describe('Article', () => {
|
|||
// Always use HEAD for downloads to avoid timeouts
|
||||
const useHeadForDownloads = true;
|
||||
|
||||
// Set up initialization for tests
|
||||
before(() => {
|
||||
// Initialize the broken links report
|
||||
cy.task('initializeBrokenLinksReport');
|
||||
});
|
||||
|
||||
// Helper function to identify download links
|
||||
function isDownloadLink(href) {
|
||||
// Check for common download file extensions
|
||||
|
@ -56,7 +62,7 @@ describe('Article', () => {
|
|||
};
|
||||
|
||||
function handleFailedLink(url, status, type, redirectChain = '') {
|
||||
// Report broken link to the task which will handle reporting
|
||||
// Report the broken link
|
||||
cy.task('reportBrokenLink', {
|
||||
url: url + redirectChain,
|
||||
status,
|
||||
|
@ -65,6 +71,7 @@ describe('Article', () => {
|
|||
page: pageUrl,
|
||||
});
|
||||
|
||||
// Throw error for broken links
|
||||
throw new Error(
|
||||
`BROKEN ${type.toUpperCase()} LINK: ${url} (status: ${status})${redirectChain} on ${pageUrl}`
|
||||
);
|
||||
|
@ -109,11 +116,7 @@ describe('Article', () => {
|
|||
}
|
||||
}
|
||||
|
||||
// Before all tests, initialize the report
|
||||
before(() => {
|
||||
cy.task('initializeBrokenLinksReport');
|
||||
});
|
||||
|
||||
// Test implementation for subjects
|
||||
subjects.forEach((subject) => {
|
||||
it(`${subject} has valid internal links`, function () {
|
||||
cy.visit(`${subject}`, { timeout: 20000 });
|
||||
|
@ -186,8 +189,19 @@ describe('Article', () => {
|
|||
});
|
||||
|
||||
it(`${subject} has valid external links`, function () {
|
||||
// Check if we should skip external links entirely
|
||||
if (Cypress.env('skipExternalLinks') === true) {
|
||||
cy.log(
|
||||
'Skipping all external links as configured by skipExternalLinks'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
cy.visit(`${subject}`);
|
||||
|
||||
// Define allowed external domains to test
|
||||
const allowedExternalDomains = ['github.com', 'kapa.ai'];
|
||||
|
||||
// Test external links
|
||||
cy.get('article, .api-content').then(($article) => {
|
||||
// Find links without failing the test if none are found
|
||||
|
@ -197,8 +211,29 @@ describe('Article', () => {
|
|||
return;
|
||||
}
|
||||
|
||||
cy.debug(`Found ${$links.length} external links`);
|
||||
cy.wrap($links).each(($a) => {
|
||||
// Filter links to only include allowed domains
|
||||
const $allowedLinks = $links.filter((_, el) => {
|
||||
const href = el.getAttribute('href');
|
||||
try {
|
||||
const url = new URL(href);
|
||||
return allowedExternalDomains.some(
|
||||
(domain) =>
|
||||
url.hostname === domain || url.hostname.endsWith(`.${domain}`)
|
||||
);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if ($allowedLinks.length === 0) {
|
||||
cy.log('No links to allowed external domains found on this page');
|
||||
return;
|
||||
}
|
||||
|
||||
cy.log(
|
||||
`Found ${$allowedLinks.length} links to allowed external domains to test`
|
||||
);
|
||||
cy.wrap($allowedLinks).each(($a) => {
|
||||
const href = $a.attr('href');
|
||||
const linkText = $a.text().trim();
|
||||
testLink(href, linkText, subject);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import fs from 'fs';
|
||||
|
||||
export const BROKEN_LINKS_FILE = '/tmp/broken_links_report.json';
|
||||
export const FIRST_BROKEN_LINK_FILE = '/tmp/first_broken_link.json';
|
||||
const SOURCES_FILE = '/tmp/test_subjects_sources.json';
|
||||
|
||||
/**
|
||||
|
@ -18,7 +19,29 @@ export function readBrokenLinksReport() {
|
|||
|
||||
try {
|
||||
const fileContent = fs.readFileSync(BROKEN_LINKS_FILE, 'utf8');
|
||||
return fileContent && fileContent !== '[]' ? JSON.parse(fileContent) : [];
|
||||
|
||||
// Check if the file is empty or contains only an empty array
|
||||
if (!fileContent || fileContent.trim() === '' || fileContent === '[]') {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Try to parse the JSON content
|
||||
try {
|
||||
const parsedContent = JSON.parse(fileContent);
|
||||
|
||||
// Ensure the parsed content is an array
|
||||
if (!Array.isArray(parsedContent)) {
|
||||
console.error('Broken links report is not an array');
|
||||
return [];
|
||||
}
|
||||
|
||||
return parsedContent;
|
||||
} catch (parseErr) {
|
||||
console.error(
|
||||
`Error parsing broken links report JSON: ${parseErr.message}`
|
||||
);
|
||||
return [];
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Error reading broken links report: ${err.message}`);
|
||||
return [];
|
||||
|
@ -57,11 +80,29 @@ export function displayBrokenLinksReport(brokenLinksReport = null) {
|
|||
brokenLinksReport = readBrokenLinksReport();
|
||||
}
|
||||
|
||||
if (!brokenLinksReport || brokenLinksReport.length === 0) {
|
||||
console.log('✅ No broken links detected');
|
||||
// Check both the report and first broken link file to determine if we have broken links
|
||||
const firstBrokenLink = readFirstBrokenLink();
|
||||
|
||||
// Only report "no broken links" if both checks pass
|
||||
if (
|
||||
(!brokenLinksReport || brokenLinksReport.length === 0) &&
|
||||
!firstBrokenLink
|
||||
) {
|
||||
console.log('✅ No broken links detected in the validation report');
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Special case: check if the single broken link file could be missing from the report
|
||||
if (
|
||||
firstBrokenLink &&
|
||||
(!brokenLinksReport || brokenLinksReport.length === 0)
|
||||
) {
|
||||
console.error(
|
||||
'\n⚠️ Warning: First broken link record exists but no links in the report.'
|
||||
);
|
||||
console.error('This could indicate a reporting issue.');
|
||||
}
|
||||
|
||||
// Load sources mapping
|
||||
const sourcesMapping = readSourcesMapping();
|
||||
|
||||
|
@ -70,6 +111,21 @@ export function displayBrokenLinksReport(brokenLinksReport = null) {
|
|||
console.error(' 🚨 BROKEN LINKS DETECTED 🚨 ');
|
||||
console.error('='.repeat(80));
|
||||
|
||||
// Show first failing link if available
|
||||
if (firstBrokenLink) {
|
||||
console.error('\n🔴 FIRST FAILING LINK:');
|
||||
console.error(` URL: ${firstBrokenLink.url}`);
|
||||
console.error(` Status: ${firstBrokenLink.status}`);
|
||||
console.error(` Type: ${firstBrokenLink.type}`);
|
||||
console.error(` Page: ${firstBrokenLink.page}`);
|
||||
if (firstBrokenLink.linkText) {
|
||||
console.error(
|
||||
` Link text: "${firstBrokenLink.linkText.substring(0, 50)}${firstBrokenLink.linkText.length > 50 ? '...' : ''}"`
|
||||
);
|
||||
}
|
||||
console.error('-'.repeat(40));
|
||||
}
|
||||
|
||||
let totalBrokenLinks = 0;
|
||||
|
||||
brokenLinksReport.forEach((report) => {
|
||||
|
@ -106,12 +162,51 @@ export function displayBrokenLinksReport(brokenLinksReport = null) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Initialize the broken links report file
|
||||
* Reads the first broken link info from the file system
|
||||
* @returns {Object|null} First broken link data or null if not found
|
||||
*/
|
||||
export function readFirstBrokenLink() {
|
||||
if (!fs.existsSync(FIRST_BROKEN_LINK_FILE)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const fileContent = fs.readFileSync(FIRST_BROKEN_LINK_FILE, 'utf8');
|
||||
|
||||
// Check if the file is empty or contains whitespace only
|
||||
if (!fileContent || fileContent.trim() === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Try to parse the JSON content
|
||||
try {
|
||||
return JSON.parse(fileContent);
|
||||
} catch (parseErr) {
|
||||
console.error(
|
||||
`Error parsing first broken link JSON: ${parseErr.message}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Error reading first broken link: ${err.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the broken links report files
|
||||
* @returns {boolean} True if initialization was successful
|
||||
*/
|
||||
export function initializeReport() {
|
||||
try {
|
||||
// Create an empty array for the broken links report
|
||||
fs.writeFileSync(BROKEN_LINKS_FILE, '[]', 'utf8');
|
||||
|
||||
// Reset the first broken link file by creating an empty file
|
||||
// Using empty string as a clear indicator that no broken link has been recorded yet
|
||||
fs.writeFileSync(FIRST_BROKEN_LINK_FILE, '', 'utf8');
|
||||
|
||||
console.debug('🔄 Initialized broken links reporting system');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(`Error initializing broken links report: ${err.message}`);
|
||||
|
|
|
@ -5,8 +5,30 @@
|
|||
* It handles starting a local Hugo server, mapping content files to their URLs, running Cypress tests,
|
||||
* and reporting broken links.
|
||||
*
|
||||
* Usage: node run-e2e-specs.js [file paths...] [--spec test-spec-path]
|
||||
*
|
||||
* Usage: node run-e2e-specs.js [file paths...] [--spec test // Display broken links report
|
||||
const brokenLinksCount = displayBrokenLinksReport();
|
||||
|
||||
// Check if we might have special case failures
|
||||
const hasSpecialCaseFailures =
|
||||
results &&
|
||||
results.totalFailed > 0 &&
|
||||
brokenLinksCount === 0;
|
||||
|
||||
if (hasSpecialCaseFailures) {
|
||||
console.warn(
|
||||
`ℹ️ Note: Tests failed (${results.totalFailed}) but no broken links were reported. This may be due to special case URLs (like Reddit) that return expected status codes.`
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
(results && results.totalFailed && results.totalFailed > 0 && !hasSpecialCaseFailures) ||
|
||||
brokenLinksCount > 0
|
||||
) {
|
||||
console.error(
|
||||
`⚠️ Tests failed: ${results.totalFailed || 0} test(s) failed, ${brokenLinksCount || 0} broken links found`
|
||||
);
|
||||
cypressFailed = true;
|
||||
exitCode = 1; *
|
||||
* Example: node run-e2e-specs.js content/influxdb/v2/write-data.md --spec cypress/e2e/content/article-links.cy.js
|
||||
*/
|
||||
|
||||
|
@ -17,7 +39,7 @@ import path from 'path';
|
|||
import cypress from 'cypress';
|
||||
import net from 'net';
|
||||
import matter from 'gray-matter';
|
||||
import { displayBrokenLinksReport } from './link-reporter.js';
|
||||
import { displayBrokenLinksReport, initializeReport } from './link-reporter.js';
|
||||
import {
|
||||
HUGO_PORT,
|
||||
HUGO_LOG_FILE,
|
||||
|
@ -144,53 +166,82 @@ async function main() {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
// 1. Map file paths to URLs and write to file
|
||||
const mapProc = spawn('node', [MAP_SCRIPT, ...fileArgs], {
|
||||
stdio: ['ignore', 'pipe', 'inherit'],
|
||||
// Separate content files from non-content files
|
||||
const contentFiles = fileArgs.filter((file) => file.startsWith('content/'));
|
||||
const nonContentFiles = fileArgs.filter(
|
||||
(file) => !file.startsWith('content/')
|
||||
);
|
||||
|
||||
// Log what we're processing
|
||||
if (contentFiles.length > 0) {
|
||||
console.log(
|
||||
`Processing ${contentFiles.length} content files for URL mapping...`
|
||||
);
|
||||
}
|
||||
|
||||
if (nonContentFiles.length > 0) {
|
||||
console.log(
|
||||
`Found ${nonContentFiles.length} non-content files that will be passed directly to tests...`
|
||||
);
|
||||
}
|
||||
|
||||
let urlList = [];
|
||||
|
||||
// Only run the mapper if we have content files
|
||||
if (contentFiles.length > 0) {
|
||||
// 1. Map file paths to URLs and write to file
|
||||
const mapProc = spawn('node', [MAP_SCRIPT, ...contentFiles], {
|
||||
stdio: ['ignore', 'pipe', 'inherit'],
|
||||
});
|
||||
|
||||
const mappingOutput = [];
|
||||
mapProc.stdout.on('data', (chunk) => {
|
||||
mappingOutput.push(chunk.toString());
|
||||
});
|
||||
|
||||
await new Promise((res) => mapProc.on('close', res));
|
||||
|
||||
// Process the mapping output
|
||||
urlList = mappingOutput
|
||||
.join('')
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
.map((line) => {
|
||||
// Parse the URL|SOURCE format
|
||||
if (line.includes('|')) {
|
||||
const [url, source] = line.split('|');
|
||||
return { url, source };
|
||||
} else if (line.startsWith('/')) {
|
||||
// Handle URLs without source (should not happen with our new code)
|
||||
return { url: line, source: null };
|
||||
} else {
|
||||
// Skip log messages
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Boolean); // Remove null entries
|
||||
}
|
||||
|
||||
// Add non-content files directly to be tested, using their path as both URL and source
|
||||
nonContentFiles.forEach((file) => {
|
||||
urlList.push({ url: file, source: file });
|
||||
});
|
||||
|
||||
const mappingOutput = [];
|
||||
mapProc.stdout.on('data', (chunk) => {
|
||||
mappingOutput.push(chunk.toString());
|
||||
});
|
||||
|
||||
await new Promise((res) => mapProc.on('close', res));
|
||||
|
||||
// Process the mapping output
|
||||
const urlList = mappingOutput
|
||||
.join('')
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
.map((line) => {
|
||||
// Parse the URL|SOURCE format
|
||||
if (line.includes('|')) {
|
||||
const [url, source] = line.split('|');
|
||||
return { url, source };
|
||||
} else if (line.startsWith('/')) {
|
||||
// Handle URLs without source (should not happen with our new code)
|
||||
return { url: line, source: null };
|
||||
} else {
|
||||
// Skip log messages
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Boolean); // Remove null entries
|
||||
|
||||
// Log the URLs and sources we'll be testing
|
||||
console.log(`Found ${urlList.length} URLs to test:`);
|
||||
console.log(`Found ${urlList.length} items to test:`);
|
||||
urlList.forEach(({ url, source }) => {
|
||||
console.log(` URL: ${url}`);
|
||||
console.log(` PAGE CONTENT SOURCE: ${source}`);
|
||||
console.log(` URL/FILE: ${url}`);
|
||||
console.log(` SOURCE: ${source}`);
|
||||
console.log('---');
|
||||
});
|
||||
|
||||
if (urlList.length === 0) {
|
||||
console.log('No URLs to test.');
|
||||
console.log('No URLs or files to test.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Write just the URLs to the test_subjects file for Cypress
|
||||
// Write just the URLs/files to the test_subjects file for Cypress
|
||||
fs.writeFileSync(URLS_FILE, urlList.map((item) => item.url).join(','));
|
||||
|
||||
// Add source information to a separate file for reference during reporting
|
||||
|
@ -320,6 +371,10 @@ async function main() {
|
|||
// 4. Run Cypress tests
|
||||
let cypressFailed = false;
|
||||
try {
|
||||
// Initialize/clear broken links report before running tests
|
||||
console.log('Initializing broken links report...');
|
||||
initializeReport();
|
||||
|
||||
console.log(`Running Cypress tests for ${urlList.length} URLs...`);
|
||||
const cypressOptions = {
|
||||
reporter: 'junit',
|
||||
|
@ -334,6 +389,8 @@ async function main() {
|
|||
test_subjects: urlList.map((item) => item.url).join(','),
|
||||
// Add new structured data with source information
|
||||
test_subjects_data: JSON.stringify(urlList),
|
||||
// Skip testing external links (non-influxdata.com URLs)
|
||||
skipExternalLinks: true,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -347,12 +404,24 @@ async function main() {
|
|||
// Process broken links report
|
||||
const brokenLinksCount = displayBrokenLinksReport();
|
||||
|
||||
if (
|
||||
(results && results.totalFailed && results.totalFailed > 0) ||
|
||||
brokenLinksCount > 0
|
||||
) {
|
||||
// Determine why tests failed
|
||||
const testFailureCount = results?.totalFailed || 0;
|
||||
|
||||
if (testFailureCount > 0 && brokenLinksCount === 0) {
|
||||
console.warn(
|
||||
`ℹ️ Note: ${testFailureCount} test(s) failed but no broken links were detected in the report.`
|
||||
);
|
||||
console.warn(
|
||||
` This usually indicates test errors unrelated to link validation.`
|
||||
);
|
||||
|
||||
// We should not consider special case domains (those with expected errors) as failures
|
||||
// but we'll still report other test failures
|
||||
cypressFailed = true;
|
||||
exitCode = 1;
|
||||
} else if (brokenLinksCount > 0) {
|
||||
console.error(
|
||||
`⚠️ Tests failed: ${results.totalFailed || 0} test(s) failed, ${brokenLinksCount || 0} broken links found`
|
||||
`⚠️ Tests failed: ${brokenLinksCount} broken link(s) detected`
|
||||
);
|
||||
cypressFailed = true;
|
||||
exitCode = 1;
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
"test:links:kapacitor": "node cypress/support/run-e2e-specs.js --spec \"cypress/e2e/content/article-links.cy.js\" content/kapacitor/**/*.{md,html}",
|
||||
"test:links:telegraf": "node cypress/support/run-e2e-specs.js --spec \"cypress/e2e/content/article-links.cy.js\" content/telegraf/**/*.{md,html}",
|
||||
"test:links:shared": "node cypress/support/run-e2e-specs.js --spec \"cypress/e2e/content/article-links.cy.js\" content/shared/**/*.{md,html}",
|
||||
"test:links:api-docs": "export cypress_base_url=\"http://localhost:1315\" cypress_test_subjects=\"/influxdb3/core/api/,/influxdb3/enterprise/api/,/influxdb3/cloud-dedicated/api/,/influxdb3/cloud-dedicated/api/v1/,/influxdb/cloud-dedicated/api/v1/,/influxdb/cloud-dedicated/api/management/,/influxdb3/cloud-dedicated/api/management/\"; npx cypress run --spec cypress/e2e/content/article-links.cy.js",
|
||||
"test:links:api-docs": "node cypress/support/run-e2e-specs.js --spec \"cypress/e2e/content/article-links.cy.js\" /influxdb3/core/api/,/influxdb3/enterprise/api/,/influxdb3/cloud-dedicated/api/,/influxdb3/cloud-dedicated/api/v1/,/influxdb/cloud-dedicated/api/v1/,/influxdb/cloud-dedicated/api/management/,/influxdb3/cloud-dedicated/api/management/",
|
||||
"test:shortcode-examples": "node cypress/support/run-e2e-specs.js --spec \"cypress/e2e/content/article-links.cy.js\" content/example.md"
|
||||
},
|
||||
"main": "assets/js/main.js",
|
||||
|
|
Loading…
Reference in New Issue