const assert = require("assert"); const fs = require("fs"); const path = require("path"); const pages = ["demand/index.vue", "demand/environment.vue", "demand/people.vue", "demand/consumer-behavior.vue", "demand/consumer-scenario.vue", "demand/feature-conversion.vue", "product/index.vue", "product/differentiation.vue", "product/structure.vue", "product/after-sales-service.vue", "product/components/ProductStandardTrainingPage.vue", "channel/supplier.vue", "channel/index.vue", "product/price.vue", "assessment/optimization.vue", "assessment/diagnosis.vue"]; for (const pageName of pages) { const page = fs.readFileSync(path.resolve(__dirname, `../src/views/${pageName}`), "utf8"); const tab = page; const connector = page; assert.match(tab, /min-width:\s*0;/, `${pageName} should let standard step tabs share the available width`); assert.match(page, /background:\s*linear-gradient\(115deg,\s*rgba\(4,\s*109,\s*155,\s*0\.78\),\s*rgba\(5,\s*62,\s*102,\s*0\.64\)\);/, `${pageName} should use the standard active-step gradient`); assert.match(connector, /overflow:\s*visible;/, `${pageName} should not clip the standard connector arrow`); assert.match(page, /right:\s*-1px;/, `${pageName} should position the standard connector arrow outside the line end`); } const peoplePage = fs.readFileSync(path.resolve(__dirname, "../src/views/demand/people.vue"), "utf8"); assert.match(peoplePage, /class="step-connector" aria-hidden="true"><\/span>/, "people.vue should use the standard CSS connector instead of a text arrow"); const behaviorPage = fs.readFileSync(path.resolve(__dirname, "../src/views/demand/consumer-behavior.vue"), "utf8"); assert.match(behaviorPage, /class="step-connector" aria-hidden="true"><\/span>/, "consumer-behavior.vue should use the standard CSS connector instead of a text arrow"); const scenarioPage = fs.readFileSync(path.resolve(__dirname, "../src/views/demand/consumer-scenario.vue"), "utf8"); assert.match(scenarioPage, /class="step-connector" aria-hidden="true"><\/span>/, "consumer-scenario.vue should use the standard CSS connector instead of a text arrow"); const conversionPage = fs.readFileSync(path.resolve(__dirname, "../src/views/demand/feature-conversion.vue"), "utf8"); assert.match(conversionPage, /class="step-connector" aria-hidden="true"><\/span>/, "feature-conversion.vue should use the standard CSS connector instead of a text arrow"); const differentiationPage = fs.readFileSync(path.resolve(__dirname, "../src/views/product/differentiation.vue"), "utf8"); assert.match(differentiationPage, /class="step-connector" aria-hidden="true"><\/span>/, "differentiation.vue should use the standard CSS connector instead of a text arrow"); const structurePage = fs.readFileSync(path.resolve(__dirname, "../src/views/product/structure.vue"), "utf8"); assert.match(structurePage, /class="step-connector" aria-hidden="true"><\/span>/, "structure.vue should use the standard CSS connector instead of a text arrow"); const afterSalesPage = fs.readFileSync(path.resolve(__dirname, "../src/views/product/after-sales-service.vue"), "utf8"); assert.match(afterSalesPage, /class="step-connector" aria-hidden="true"><\/span>/, "after-sales-service.vue should use the standard CSS connector instead of a text arrow"); const productStandardPage = fs.readFileSync(path.resolve(__dirname, "../src/views/product/components/ProductStandardTrainingPage.vue"), "utf8"); assert.match(productStandardPage, /class="step-connector" aria-hidden="true"><\/span>/, "ProductStandardTrainingPage.vue should use the standard CSS connector instead of a text arrow"); const supplierPage = fs.readFileSync(path.resolve(__dirname, "../src/views/channel/supplier.vue"), "utf8"); assert.match(supplierPage, /class="step-connector" aria-hidden="true"><\/span>/, "supplier.vue should use the standard CSS connector instead of a text arrow"); const channelPage = fs.readFileSync(path.resolve(__dirname, "../src/views/channel/index.vue"), "utf8"); assert.match(channelPage, /class="step-connector" aria-hidden="true"><\/span>/, "channel/index.vue should use the standard CSS connector instead of a text arrow"); const pricePage = fs.readFileSync(path.resolve(__dirname, "../src/views/product/price.vue"), "utf8"); assert.match(pricePage, /class="step-connector" aria-hidden="true"><\/span>/, "price.vue should use the standard CSS connector instead of a text arrow"); const optimizationPage = fs.readFileSync(path.resolve(__dirname, "../src/views/assessment/optimization.vue"), "utf8"); assert.match(optimizationPage, /class="step-connector" aria-hidden="true"><\/span>/, "optimization.vue should use the standard CSS connector instead of a text arrow"); const diagnosisPage = fs.readFileSync(path.resolve(__dirname, "../src/views/assessment/diagnosis.vue"), "utf8"); assert.match(diagnosisPage, /class="step-connector" aria-hidden="true"><\/span>/, "diagnosis.vue should use the standard CSS connector instead of a text arrow"); assert.doesNotMatch(diagnosisPage, /

Training Task<\/p>

任务实训<\/h3>

/, "diagnosis.vue should not render the removed task-training heading or description"); assert.match(diagnosisPage, //, "diagnosis.vue should retain the training file download control"); const newProductSurveyPage = fs.readFileSync(path.resolve(__dirname, "../src/views/foundation/new-product-survey.vue"), "utf8"); assert.doesNotMatch(newProductSurveyPage, /

Training Task<\/p>[\s\S]*?

/, "new-product-survey.vue should not render the removed task-training heading or description"); assert.match(newProductSurveyPage, //, "new-product-survey.vue should retain the training file download control"); const testIndexPage = fs.readFileSync(path.resolve(__dirname, "../src/views/test/index.vue"), "utf8"); assert.match(testIndexPage, /@media \(max-width: 1100px\)[\s\S]*?grid-template-columns: 1fr;/, "test/index.vue should keep the standard desktop two-column layout until the 1100px breakpoint"); const promotionPage = fs.readFileSync(path.resolve(__dirname, "../src/views/test/promotion.vue"), "utf8"); assert.match(promotionPage, /@media \(max-width: 900px\)[\s\S]*?\.promotion-phase :deep\(\.el-button\) \{ width: 100%; \}/, "test/promotion.vue should switch the standard training controls to the mobile layout at 900px"); const studentTaskWorkbenchPages = [ "training/GenericTrainingPage.vue", "product/components/ProductStandardTrainingPage.vue", "foundation/new-product-survey.vue", "foundation/product-development-factors.vue", "demand/index.vue", "demand/environment.vue", "demand/people.vue", "demand/consumer-behavior.vue", "demand/consumer-scenario.vue", "demand/feature-conversion.vue", "product/index.vue", "product/price.vue", "product/differentiation.vue", "product/structure.vue", "product/after-sales-service.vue", "channel/index.vue", "channel/supplier.vue", "assessment/diagnosis.vue", "assessment/optimization.vue" ]; for (const pageName of studentTaskWorkbenchPages) { const page = fs.readFileSync(path.resolve(__dirname, `../src/views/${pageName}`), "utf8"); assert.doesNotMatch(page, /class="workbench-head">\s*

[\s\S]*?workbench-description/, `${pageName} should not render the task-workbench heading or description`); assert.match(page, /TrainingMaterialButton|class="material-download"/, `${pageName} should retain the file download control`); } console.log("Demand index step navigation matches the standard-page treatment.");