Skip to content

Commit

Permalink
Glossary unit tests, fix a few caching issues in previous ones
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Yu committed Oct 3, 2024
1 parent e54910f commit 604bd71
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 88 deletions.
10 changes: 5 additions & 5 deletions src/compile/recipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ export async function build(rootFile: string, langId: string, buildLoop: () => P

// Create output subdirectories for included files
if (tools?.map(tool => tool.command).includes('latexmk') && rootFile === lw.root.subfiles.path && lw.root.file.path) {
createOutputSubFolders(lw.root.file.path)
await createOutputSubFolders(lw.root.file.path)
} else {
createOutputSubFolders(rootFile)
await createOutputSubFolders(rootFile)
}

// Check for invalid toolchain
Expand All @@ -88,14 +88,14 @@ export async function build(rootFile: string, langId: string, buildLoop: () => P
*
* @param {string} rootFile - Path to the root LaTeX file.
*/
function createOutputSubFolders(rootFile: string) {
async function createOutputSubFolders(rootFile: string) {
const rootDir = path.dirname(rootFile)
let outDir = lw.file.getOutDir(rootFile)
if (!path.isAbsolute(outDir)) {
outDir = path.resolve(rootDir, outDir)
}
logger.log(`outDir: ${outDir} .`)
lw.cache.getIncludedTeX(rootFile).forEach(async file => {
for (const file of lw.cache.getIncludedTeX(rootFile)) {
const relativePath = path.dirname(file.replace(rootDir, '.'))
const fullOutDir = path.resolve(outDir, relativePath)
// To avoid issues when fullOutDir is the root dir
Expand All @@ -120,7 +120,7 @@ function createOutputSubFolders(rootFile: string) {
throw(e)
}
}
})
}
}


Expand Down
4 changes: 2 additions & 2 deletions test/suites/04_intellisense.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ suite('Intellisense test suite', () => {
assert.ok(suggestions.labels.includes('\\includefrom{}{}'))
let snippet = suggestions.items.filter(item => item.label === '\\includefrom{}{}')[0].insertText
assert.ok(snippet)
assert.ok(typeof snippet !== 'string')
assert.ok(snippet instanceof vscode.SnippetString)
assert.ok(snippet.value.includes('${1:'))

await vscode.workspace.getConfiguration('latex-workshop').update('intellisense.argumentHint.enabled', false)
Expand All @@ -151,7 +151,7 @@ suite('Intellisense test suite', () => {
assert.ok(suggestions.labels.includes('\\includefrom{}{}'))
snippet = suggestions.items.filter(item => item.label === '\\includefrom{}{}')[0].insertText
assert.ok(snippet)
assert.ok(typeof snippet !== 'string')
assert.ok(snippet instanceof vscode.SnippetString)
assert.ok(!snippet.value.includes('${1:'))
})

Expand Down
133 changes: 79 additions & 54 deletions test/units/03_core_cache.test.ts

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions test/units/04_core_root.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,7 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {

set.config('latex.search.rootFiles.include', [ `${fixture}/find_workspace/**/*.tex` ])
set.root(fixture, 'find_workspace', 'main.tex')
const stub = mock.activeTextEditor(texPath, '\\documentclass{article}\n')
await lw.root.find()
stub.restore()

assert.hasLog('Try finding root from current workspaceRootDir:')
assert.strictEqual(lw.root.file.path, texPath)
Expand Down
3 changes: 2 additions & 1 deletion test/units/06_compile_recipe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {
})

afterEach(() => {
queue.clear()
getOutDirStub.resetHistory()
getIncludedTeXStub.resetHistory()
mkdirStub.resetHistory()
Expand Down Expand Up @@ -186,7 +187,6 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {
})

describe('lw.compile->recipe.createOutputSubFolders', () => {

beforeEach(() => {
getIncludedTeXStub.returns([ set.root('main.tex') ])
})
Expand Down Expand Up @@ -226,6 +226,7 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {
await build(rootFile, 'latex', async () => {})
stub.restore()

assert.strictEqual(mkdirStub.callCount, 1)
assert.pathStrictEqual(mkdirStub.getCall(0).args[0] as string, expectedOutDir)
assert.deepStrictEqual(mkdirStub.getCall(0).args[1], { recursive: true })
})
Expand Down
1 change: 1 addition & 0 deletions test/units/11_parser_tex.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type * as Ast from '@unified-latex/unified-latex-types'
describe(path.basename(__filename).split('.')[0] + ':', () => {
before(() => {
mock.init(lw, 'parser')
;(lw.cache.paths as sinon.SinonStub).returns([])
})

after(() => {
Expand Down
12 changes: 6 additions & 6 deletions test/units/15_completion_macro.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {

const suggestion = getSuggestions().find(s => s.label === '\\RenewAcroPreset{}{}')
const snippet = suggestion?.insertText
assert.ok(typeof snippet !== 'string')
assert.ok(!snippet?.value.includes('%keyvals'), snippet?.value)
assert.ok(snippet instanceof vscode.SnippetString)
assert.ok(!snippet.value.includes('%keyvals'), snippet?.value)
})

it('should not provide argument hints if `intellisense.argumentHint.enabled` is false', async () => {
Expand All @@ -126,14 +126,14 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {

let suggestion = getSuggestions().find(s => s.label === '\\includefrom{}{}')
let snippet = suggestion?.insertText
assert.ok(typeof snippet !== 'string')
assert.ok(snippet?.value.includes('${1:'))
assert.ok(snippet instanceof vscode.SnippetString)
assert.ok(snippet.value.includes('${1:'))

set.config('intellisense.argumentHint.enabled', false)
suggestion = getSuggestions().find(s => s.label === '\\includefrom{}{}')
snippet = suggestion?.insertText
assert.ok(typeof snippet !== 'string')
assert.ok(!snippet?.value.includes('${1:'))
assert.ok(snippet instanceof vscode.SnippetString)
assert.ok(!snippet.value.includes('${1:'))
})

it('should add new macros from `intellisense.command.user`', async () => {
Expand Down
10 changes: 10 additions & 0 deletions test/units/18_completion_package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,15 @@ describe(path.basename(__filename).split('.')[0] + ':', () => {
assert.ok(labels.includes('\\import{}{}'))
assert.ok(labels.includes('\\lstinputlisting{}'))
})

it('should provide base KOMAScript macros/envs in KOMAScript class', async () => {
readStub.resolves('\\documentclass{scrartcl}')
await lw.cache.refreshCache(texPath)
const labels = getMacros()
// in class-scrartcl.cwl
assert.ok(labels.includes('\\addpart{}'))
// in base
assert.ok(labels.includes('\\addchap{}'))
})
})
})
10 changes: 1 addition & 9 deletions test/units/20_completion_documentclass.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,15 @@ import * as vscode from 'vscode'
import * as path from 'path'
import * as sinon from 'sinon'
import { lw } from '../../src/lw'
import { assert, get, mock, set } from './utils'
import { assert, get, mock } from './utils'
import { provider } from '../../src/completion/completer/class'

describe(path.basename(__filename).split('.')[0] + ':', () => {
const fixture = path.basename(__filename).split('.')[0]
const texPath = get.path(fixture, 'main.tex')
let readStub: sinon.SinonStub

before(() => {
mock.init(lw, 'root', 'cache', 'parser', 'completion')
readStub = sinon.stub(lw.file, 'read')
})

beforeEach(async () => {
set.root(texPath)
readStub.resolves('\\usepackage{import}\n\\usepackage[savemem]{listings}')
await lw.cache.refreshCache(texPath)
})

after(() => {
Expand Down
10 changes: 3 additions & 7 deletions test/units/21_completion_input.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,16 @@ import { assert, get, mock, set } from './utils'
import { inputProvider, importProvider, subimportProvider } from '../../src/completion/completer/input'
import type { CompletionProvider } from '../../src/types'

describe.only(path.basename(__filename).split('.')[0] + ':', () => {
describe(path.basename(__filename).split('.')[0] + ':', () => {
const fixture = path.basename(__filename).split('.')[0]
const texPath = get.path(fixture, 'main.tex')
let readStub: sinon.SinonStub

before(() => {
mock.init(lw, 'root', 'cache', 'parser', 'completion')
readStub = sinon.stub(lw.file, 'read')
})

beforeEach(async () => {
beforeEach(() => {
set.root(texPath)
readStub.resolves('\\usepackage{import}\n\\usepackage[savemem]{listings}')
await lw.cache.refreshCache(texPath)
})

after(() => {
Expand Down Expand Up @@ -79,7 +75,7 @@ describe.only(path.basename(__filename).split('.')[0] + ':', () => {
it('should provide \\subimport subfile suggestions with extension-less inserted text', () => {
const suggestions = getSuggestions(subimportProvider, ['\\subimport{sub}{', 'import', 'sub', ''])

assert.ok(!suggestions.some(s => typeof s.insertText !== 'string' && s.insertText?.value.includes('.tex')))
assert.ok(!suggestions.some(s => s.insertText instanceof vscode.SnippetString && s.insertText?.value.includes('.tex')))
})
})
})
110 changes: 110 additions & 0 deletions test/units/22_completion_glossary.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import * as vscode from 'vscode'
import * as path from 'path'
import * as sinon from 'sinon'
import { lw } from '../../src/lw'
import { assert, get, mock, set } from './utils'
import { provider } from '../../src/completion/completer/glossary'

describe(path.basename(__filename).split('.')[0] + ':', () => {
const fixture = path.basename(__filename).split('.')[0]
const texPath = get.path(fixture, 'main.tex')
const glsPath = get.path(fixture, 'gls.tex')
let readStub: sinon.SinonStub

before(() => {
mock.init(lw, 'root', 'cache', 'parser', 'completion')
readStub = sinon.stub(lw.file, 'read')
})

beforeEach(() => {
set.root(texPath)
})

after(() => {
sinon.restore()
})

describe('lw.completion->glossary', () => {
function getSuggestions() {
return provider.from(['', ''], {
uri: vscode.Uri.file(texPath),
langId: 'latex',
line: '',
position: new vscode.Position(0, 0),
})
}

it('should parse and provide \\newacronym definition', async () => {
readStub.resolves('\\newacronym{rf}{RF}{radio-frequency}')
await lw.cache.refreshCache(texPath)

const suggestions = getSuggestions()

assert.ok(suggestions.some(s => s.label === 'rf'))
assert.strictEqual(suggestions.find(s => s.label === 'rf')?.detail, 'radio-frequency')
})

it('should reject ill-formed glossary definitions', async () => {
readStub.resolves('\\newacronym[argopt]{EPE_x}{E} % ill-formed entry')
await lw.cache.refreshCache(texPath)

const suggestions = getSuggestions()

assert.ok(!suggestions.some(s => s.label === 'EPE_x'))
})

it('should parse and provide \\newglossaryentry definition', async () => {
readStub.resolves('\\newglossaryentry{vs_code}{name=VSCode, description=Editor}')
await lw.cache.refreshCache(texPath)

const suggestions = getSuggestions()

assert.ok(suggestions.some(s => s.label === 'vs_code'))
assert.strictEqual(suggestions.find(s => s.label === 'vs_code')?.detail, 'Editor')
})

it('should parse and provide \\newglossaryentry definition with curly brace fence', async () => {
readStub.resolves('\\newglossaryentry{lw}{name={LaTeX Workshop}, description={What this extension is $\\mathbb{A}$}}')
await lw.cache.refreshCache(texPath)

const suggestions = getSuggestions()

assert.ok(suggestions.some(s => s.label === 'lw'))
assert.strictEqual(suggestions.find(s => s.label === 'lw')?.detail, 'What this extension is $\\mathbb{A}$')
})

it('should parse and provide \\newabbr definition', async () => {
readStub.resolves('\\newabbr{abbr_x}{Ebbr}{A first abbreviation}')
await lw.cache.refreshCache(texPath)

const suggestions = getSuggestions()

assert.ok(suggestions.some(s => s.label === 'abbr_x'))
assert.strictEqual(suggestions.find(s => s.label === 'abbr_x')?.detail, 'A first abbreviation')
})

it('should parse and provide \\newabbreviation definition', async () => {
readStub.resolves('\\newabbreviation[optional arg]{abbr_y}{Ybbr}{A second abbreviation}')
await lw.cache.refreshCache(texPath)

const suggestions = getSuggestions()

assert.ok(suggestions.some(s => s.label === 'abbr_y'))
assert.strictEqual(suggestions.find(s => s.label === 'abbr_y')?.detail, 'A second abbreviation')
})

it('should parse and provide glossary definitions in another file given in \\loadglsentries', async () => {
const stub = sinon.stub(lw.file, 'exists').resolves({ type: 1, ctime: 0, mtime: 0, size: 0 })
readStub.resolves('\\newacronym{rf}{RF}{radio-frequency}')
readStub.withArgs(texPath).resolves('\\loadglsentries{gls}')
await lw.cache.refreshCache(texPath)
await lw.cache.refreshCache(glsPath)
stub.restore()

const suggestions = getSuggestions()

assert.ok(suggestions.some(s => s.label === 'rf'))
assert.strictEqual(suggestions.find(s => s.label === 'rf')?.detail, 'radio-frequency')
})
})
})
4 changes: 2 additions & 2 deletions test/units/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ export function run(): Promise<void> {
const mocha = new Mocha({
ui: 'bdd',
color: true,
timeout: process.env['LATEXWORKSHOP_CITEST'] ? 10000 : 8000,
retries: process.env['LATEXWORKSHOP_CITEST'] ? 8 : 2
timeout: process.env['LATEXWORKSHOP_CITEST'] ? 10000 : 5000,
retries: process.env['LATEXWORKSHOP_CITEST'] ? 2 : 0
})

mocha.suite.on('pre-require', (context) => {
Expand Down

0 comments on commit 604bd71

Please sign in to comment.