Skip to content

Commit

Permalink
feat(ui/testing): new specs script arg: "--test" (dry-run create + va…
Browse files Browse the repository at this point in the history
…lidate)
  • Loading branch information
rstoenescu committed Mar 29, 2024
1 parent 7a63169 commit 881803b
Show file tree
Hide file tree
Showing 20 changed files with 186 additions and 90 deletions.
2 changes: 1 addition & 1 deletion ui/build/build.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const apiValueRegex = {
Boolean: /^(true|false)$/,
Function: / => /,
RegExp: /^\/.*\/[gimuy]*$/,
Element: /(^document\.?|^\..+|^#.+|^body\.?|.+El$|\$refs)/,
Element: /(^document\.|^\..+|^#.+|.+El$|\$refs)/,
Component: /^[A-Z][A-Za-z]+$/,
'Promise<any>': apiValuePromiseRegex,
'Promise<void>': apiValuePromiseRegex,
Expand Down
2 changes: 1 addition & 1 deletion ui/src/api.extends.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
".scroll-target-class",
"#scroll-target-id",
"$refs.scrollTarget",
"body"
"document.body"
],
"category": "behavior"
},
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/btn-dropdown/QBtnDropdown.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"desc": "Class definitions to be attributed to the menu",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/editor/QEditor.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@
"desc": "CSS classes for the input area",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/fab/use-fab.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"desc": "Class definitions to be attributed to the label container",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/file/QFile.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"desc": "Class definitions to be attributed to the underlying selection container",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/input/QInput.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"desc": "Class definitions to be attributed to the underlying input tag",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/pagination/QPagination.json
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@
"desc": "Class definitions to be attributed to the input (if using one)",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/select/QSelect.json
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@
"desc": "Class definitions to be attributed to the underlying input tag",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand Down
6 changes: 3 additions & 3 deletions ui/src/components/splitter/QSplitter.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"desc": "Class definitions to be attributed to the 'before' panel",
"examples": [
"'bg-deep-orange'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand All @@ -66,7 +66,7 @@
"desc": "Class definitions to be attributed to the 'after' panel",
"examples": [
"'bg-deep-orange'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand All @@ -77,7 +77,7 @@
"desc": "Class definitions to be attributed to the splitter separator",
"examples": [
"'bg-deep-orange'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand Down
10 changes: 5 additions & 5 deletions ui/src/components/table/QTable.json
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@
"desc": "CSS classes to apply to native HTML <table> element's wrapper (which is a DIV)",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand All @@ -550,7 +550,7 @@
"desc": "CSS classes to apply to header of native HTML <table> (which is a TR)",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand All @@ -573,7 +573,7 @@
"examples": [
"'my-special-class'",
"'justify-center'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand All @@ -595,7 +595,7 @@
"desc": "CSS classes to apply to the card (when in grid mode) or container card (when not in grid mode)",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
],
"category": "style"
},
Expand All @@ -607,7 +607,7 @@
"examples": [
"'my-special-class'",
"'text-h1'",
"{ 'text-h1': <condition> }"
"{ 'text-h1': true }"
],
"category": "style"
},
Expand Down
8 changes: 4 additions & 4 deletions ui/src/plugins/notify/Notify.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
"desc": "Class definitions to be attributed to the badge",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
]
},

Expand All @@ -145,7 +145,7 @@
"desc": "Class definitions to be attributed to the progress bar",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
]
},

Expand Down Expand Up @@ -349,7 +349,7 @@
"desc": "Class definitions to be attributed to the badge",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
]
},

Expand All @@ -363,7 +363,7 @@
"desc": "Class definitions to be attributed to the progress bar",
"examples": [
"'my-special-class'",
"{ 'my-special-class': <condition> }"
"{ 'my-special-class': true }"
]
},

Expand Down
8 changes: 4 additions & 4 deletions ui/testing/specs/astParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function readAstJson (ctx) {
)
console.error('declaration', node.declaration)
console.error('ctx', ctx)
process.exit(1)
throw new Error('readAstJson > unknown ExportNamedDeclaration > declaration')
}
if (node.declaration.type === 'VariableDeclaration') {
node.declaration.declarations.forEach(declaration => {
Expand All @@ -101,7 +101,7 @@ export function readAstJson (ctx) {
)
console.error('declaration', declaration)
console.error('ctx', ctx)
process.exit(1)
throw new Error('readAstJson > unknown ExportNamedDeclaration > VariableDeclaration > type')
}
})
}
Expand Down Expand Up @@ -156,7 +156,7 @@ export function readAstJson (ctx) {
)
console.error('prop', prop)
console.error('ctx', ctx)
process.exit(1)
throw new Error('readAstJson > unregistered ExportDefaultDeclaration > ObjectExpression > properties')
}

const { jsonKey, def } = content[ ref ]
Expand Down Expand Up @@ -215,7 +215,7 @@ export function readAstJson (ctx) {
) {
console.error('AST: no variables, classes or functions found for:', ctx.targetAbsolute)
console.error('ctx', ctx)
process.exit(1)
throw new Error('readAstJson > no variables, classes or functions found')
}

if (hasVariables === false) {
Expand Down
86 changes: 86 additions & 0 deletions ui/testing/specs/cmd.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { relative } from 'node:path'
import { fileURLToPath } from 'node:url'
import fse from 'fs-extra'

import { getTestFile } from './testFile.js'

const testFilePath = fileURLToPath(new URL('./__temp.js', import.meta.url))
const rootFolder = fileURLToPath(new URL('../..', import.meta.url))

const ctxOverride = {
testFileAbsolute: testFilePath,
testFileRelative: relative(rootFolder, testFilePath)
}

/**
* Dry-run test of create + validate
*/
export async function cmdTest ({
ctx,
testFile
}) {
console.log(`\n 🍕 Testing ${ ctx.targetRelative }:`)

let testFileContent
try {
testFileContent = testFile.createContent()
}
catch (err) {
console.error(' ❌ Failed createContent() test (threw an error)')
console.error(err)
return
}

fse.writeFileSync(
testFilePath,
testFileContent,
'utf-8'
)

let tempTestFile
try {
tempTestFile = getTestFile({ ...ctx, ...ctxOverride })
}
catch (err) {
console.error(' ❌ Failed getTestFile() test (threw an error)')
console.error(err)
fse.unlinkSync(testFilePath)
return
}

try {
const { errors, warnings } = tempTestFile.getMisconfiguration()
if (errors.length !== 0 || warnings.length !== 0) {
console.error(' ❌ Failed getMisconfiguration() test')
console.error('errors', errors)
console.error('warnings', warnings)
fse.unlinkSync(testFilePath)
return
}
}
catch (err) {
console.error(' ❌ Failed getMisconfiguration() test (threw an error)')
console.error(err)
fse.unlinkSync(testFilePath)
return
}

try {
const missingTests = tempTestFile.getMissingTests()
if (missingTests !== null) {
console.error(' ❌ Failed getMissingTests() test')
console.log(missingTests)
fse.unlinkSync(testFilePath)
return
}
}
catch (err) {
console.error(' ❌ Failed getMissingTests() test (threw an error)')
console.error(err)
fse.unlinkSync(testFilePath)
return
}

fse.unlinkSync(testFilePath)
console.log(' ✅ Passed')
}
18 changes: 10 additions & 8 deletions ui/testing/specs/ctx.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,30 @@ import fse from 'fs-extra'
import { pascalCase } from './specs.utils.js'

const rootFolder = fileURLToPath(new URL('../..', import.meta.url))
const jsRE = /\.js$/

export function createCtx (target) {
const localName = basename(target)
const dirAbsolute = dirname(resolve(rootFolder, target))
const testName = localName.replace('.js', '.test.js')
const testFileAbsolute = resolve(dirAbsolute, testName)
const pascalName = pascalCase(localName.replace('.js', ''))
const rootName = localName.replace(jsRE, '')
const testName = rootName + '.test.js'
const targetAbsolute = resolve(rootFolder, target)
const testFileAbsolute = resolve(dirname(targetAbsolute), testName)
const pascalName = pascalCase(rootName)

const ctx = {
targetRelative: target,
targetAbsolute: resolve(rootFolder, target),
targetAbsolute,
localName,
pascalName,
dirAbsolute,
testTreeRootId: `[${ pascalName } API]`,
testFileAbsolute,
testFileRelative: relative(rootFolder, testFileAbsolute),
testTreeRootId: `[${ pascalName } API]`
testFileRelative: relative(rootFolder, testFileAbsolute)
}

let cachedTargetContent
// on demand only
Object.defineProperty(ctx, 'targetContent', {
enumerable: true,
get () {
if (cachedTargetContent === void 0) {
cachedTargetContent = fse.readFileSync(ctx.targetAbsolute, 'utf-8')
Expand Down
1 change: 1 addition & 0 deletions ui/testing/specs/ignoredTestFiles.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ src/components/table/table-pagination.js
src/components/table/table-row-expand.js
src/components/table/table-row-selection.js
src/components/table/table-sort.js
src/components/uploader/QUploaderAddTrigger.js
src/composables.js
src/composables/private/use-field.js
src/composables/private/use-file-dom-props.js
Expand Down
2 changes: 1 addition & 1 deletion ui/testing/specs/readAssociatedJsonFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function readJsonFile (ctx) {
const distJsonFile = resolve(rootFolder, 'dist/api/', jsonFileBasename)
if (fse.existsSync(distJsonFile)) return distJsonFile

const localJsonFile = resolve(ctx.dirAbsolute, jsonFileBasename)
const localJsonFile = ctx.targetAbsolute.replace('.js', '.json')
if (fse.existsSync(localJsonFile)) return localJsonFile
}

Expand Down

0 comments on commit 881803b

Please sign in to comment.