KTextEditor
Files | |
ktexteditorscripttester.cpp | |
scripttester.cpp | |
Detailed Description
ktexteditor-script-tester6
is a program used to run unit tests on javascript scripts built into KTextEditor
or written by users.
Getting Started
First, we need to load a script via loadScript
. The script will be evaluated in the context of the global object.
The path above refers to scripts integrated directly into KTextEditor
. In particular, it contains the moveLinesDown
function, which will be used in what follows.
Next, we need to write a test case using one of the 3 available functions:
testCase
sequence
withInput
Each of these functions takes a optional name as first parameter and a function as last parameter. The name is displayed in case of failure, and cli options allow you to filter what will or won't be executed. The last parameter function contains our tests on moveLinesDown
.
cmd()
executes a command on a document whose state is represented by input and checks that the final document is in the state of expected.
The document state is the text and the position of cursors and selections represented by characters called placeholder. By default, |
represents a cursor and [...]
a selection.
If no cursor position is given, it will automatically be set after the selection or at the end of the document.
Running the test gives us:
The number of successes is double that expected. This is normal, as by default cmd()
executes tests twice: once with block selection disabled, a second time with block selection enabled.
With a more verbose display (ktexteditor-script-tester6 -p test.js
) we can see the following result:
The -B
option disables tests on block selection and --dual
offers finer control. It can also be disabled directly in the test file via config()
:
If we look closely at our test, the expected result corresponds to the next test input. The whole thing can be simplified using sequence()
:
By activating verbose mode (ktexteditor-script-tester6 -B -V test.js
), we can see that the input to a test takes the expected value from the previous test:
Note that a cursor is automatically added to the input.
The default display for block selection is different (controlled by -F
), here's an extract:
Finally, withInput()
has an identical interface to sequence()
, but input doesn't change each time cmd()
is called.
Note that these functions can be called nested and that the script is started in a testCase
with an empty name.
Checking return values
There are 2 ways to check the result of a function:
- either
test(command, op, expected, msgOrInfo)
- or
cmd(command, input, expectedOutput, msgOrExpectedResultInfo)
(parameterinput
does not exist withsequence()
andwithInput()
)
All operators are stored in the TestFramework.operators
array, which a script can complete. It contains:
- classic operators:
===
,!=
,<
, etc - more advanced operators:
eqv
: converts to string then compares. Conversion is done via a dedicated function explained in the next chapter.!!
: a double negation or, more simply,Boolean(result) == expected
.between
forexpected[0] <= result < expected[1]
.inclusiveBetween
forexpected[0] <= result <= expected[1]
is
forObject.is(result, expected)
- some keywords:
instanceof
in
is type
fortypeof result === expected
.key
forexpected in result
.
- error operators:
error
,errorMsg
,errorType
,hasError
.
test()
has different aliases:
- test on Boolean:
eqvTrue(command, msgOrInfo)
= ‘test(command, ’!!', true, msgOrInfo)-
eqvFalse(command, msgOrInfo=
test(command, '!!', false, msgOrInfo)-
eqTrue(command, msgOrInfo=
test(command, '===', true, msgOrInfo)-
eqFalse(command, msgOrInfo=
test(command, '===', false, msgOrInfo)
test on errors: -
error(command, expected, msgOrInfo=
test(command, 'error', expected, msgOrInfo)-
errorMsg(command, expected, msgOrInfo=
test(command, 'errorMsg', expected, msgOrInfo)-
errorType(command, expected, msgOrInfo=
test(command, 'errorType', expected, msgOrInfo)-
hasError(command, msgOrInfo=
test(command, 'hasError', true, msgOrInfo)alias for operators: -
eqv(command, expected, msgOrInfo=
test(command, 'eqv', expected, msgOrInfo)-
is(command, expected, msgOrInfo=
test(command, 'is', expected, msgOrInfo)-
eq(command, expected, msgOrInfo=
test(command, '===', expected, msgOrInfo)-
ne(command, expected, msgOrInfo=
test(command, '!=', expected, msgOrInfo)-
lt(command, expected, msgOrInfo=
test(command, '<', expected, msgOrInfo)-
gt(command, expected, msgOrInfo=
test(command, '>', expected, msgOrInfo)-
le(command, expected, msgOrInfo=
test(command, '<=', expected, msgOrInfo)-
ge(command, expected, msgOrInfo=
test(command, '>=', expected, msgOrInfo)`
Add a string conversion function
String conversions are used for display and with the eqv
operator.
The conversion function used is TestFramework.addStringCodeFragments
which displays basic types or use functions registered with TestFramework.addStringCodeFragments.{registerClassName, registerClass, registerSymbol, register}
.
See sources in testframework.js
for details.
Command parameter
the command
parameter of cmd()
and test()
can be either
- a function
- a string to be executed in the global context (not recommended)
- an array with a function or string as the first parameter and arguments for the following parameters
Unfortunately, this doesn't work well with methods because the this
is lost:
To get around this problem, we can use calleeWrapper()
, which retains the this
and adds an object name to the function name display:
If the first parameter of calleeWrapper
is falsy, then a string representation of the object will be used.
Note that calleeWrapper
is not required with view
, document
and editor
.
For lazy evaluation of function calls as parameters, we can use lazyfn(fn, ...args)
or fn(fn, ...args)
:
To use a lazy function call in an array or object, we can use lazyarg(Array|Object)
or arg(Array|Object)
:
Placeholders
Placeholders are used with cmd()
to insert cursors or selections in the input and expected output. They are configured via config()
.
There are a total of 7 placeholders distributed in 5 configuration variables:
cursor
: represents the primary cursor. The default is ‘’|'. -
selection: represents the start and end of a selection. Default is
'[]'. -
virtualText: used with block selection to introduce spaces to place a cursor outside the document text. It must always be followed by a placeholder or new line. -
secondaryCursor: secondary cursor in multi-cursor. No default value. -
secondarySelection`: secondary selection in multi-cursor. No default value.
If the placeholder is an empty string, it will not be used.
If cursor
and secondaryCursor
have the same value, then the first cursor found will be the primary cursor. The same applies to selection.
In some cases, a placeholder may not be configured, but used in the result display. This is configured via the -S
command line option or with the following 5 configuration variables:
cursor2
: the default is ‘’|'-
selection2: the default is
'[]'-
virtualText2: the default is
'·'-
secondaryCursor2: the default is
'┆'-
secondarySelection2: the default is
'❲❳'`
These variables are also used when a placeholder has a display conflict with another placeholder.
Unlike the first 5, setting an empty value reset to default value.
Multi-line string parameter
When parameters contain several line breaks, the text may be difficult to read. For example:
This can be rewritten with concatenations in this form:
But the use of ‘’
makes reading a little confusing. To overcome this problem, a tagged template named
c` exists:
Characters at the beginning of a line up to >
will be ignored.
Constants
There are 5 special constants:
DUAL_MODE
: used with theblockSelection
configuration variable so thatcmd()
runs the test first with block selection disabled, then, if the test does not fail, with block selection enabled.ALWAYS_DUAL_MODE
: Same asDUAL_MODE
, but the 2 modes are always executed.AS_INPUT
: Special value forexpectedOutput
fromcmd()
which indicates that the expected output is the same as the input value.REUSE_LAST_INPUT
: in parameter ofsequence()
andwithInput()
, reuse the previous input.REUSE_LAST_EXPECTED_OUTPUT
: in parameter ofsequence()
andwithInput()
, use the previous expected output as input.
Interface
loadScript(path)
: load a javascript file in the context of the global object.loadModule(path)
: load a javascript file as a module.paste(str)
: pastestr
to the current position.kdb.type(str)
: insertstr
into current documment. To be used as a command:cmd([kbd.type, str], ...)
kdb.enter()
: insert a new line into current documment. To be used as a command:cmd(enter, ...)
keys(str) -> kdb.enter | [kbd.type, str]
: To be used as a command:cmd(keys(str), ...)
For full documentation, see the functions and classes exported from testframework.js
(those prefixed with export
).
TestFramework.operators
TestFramework.formatArgs(args, sep)
TestFramework.toComparableString(value)
TestFramework.functionCallToString(fn, args)
TestFramework.addStringCodeFragments(value, codeFragments, ancestors, mustBeStable)
TestFramework.addStringCodeFragments.registerClassName(name, addString)
TestFramework.addStringCodeFragments.registerClass(type, addString)
TestFramework.addStringCodeFragments.registerSymbol(symbol, addString)
TestFramework.addStringCodeFragments.register(addString)
Unless otherwise indicated, these following functions are also found in TestFramework
under the same name:
DUAL_MODE
ALWAYS_DUAL_MODE
AS_INPUT
=TestFramework.EXPECTED_OUTPUT_AS_INPUT
REUSE_LAST_INPUT
REUSE_LAST_EXPECTED_OUTPUT
calleeWrapper(name, obj, newObj)
LazyFunc(fn, ...args)
; alias:fn
,lazyfn
LazyArg(Array|Object)
; alias:arg
,lazyarg
c(strings, ...values)
(=TestFramework.sanitizeTag
): tagged templates prefix sanitizerconfig(object)
testCase(nameOrConfig: Optional[String|Object], fn)
: name is used for filter test. If it is an object, it is passed toconfig()
. An object can contain thename
property.sequence(nameOrConfig: Optional[String|Object], input, fn)
withInput(nameOrConfig: Optional[String|Object], input, fn)
print(...args)
: equivalent to ‘printSep(’ ', ...args)-
printSep(sep, ...args)`cmd(command, input, expectedOutput: String | AS_INPUT, msgOrExpectedResultInfo: undefined | String | Object)
: insidesequence()
andwithInput()
, theinput
parameter does not existxcmd(...)
: Same ascmd()
, but for an expected failure.type(str, input, expectedOutput, msgOrExpectedResultInfo)
: alias forcmd(keys(str), input, expectedOutput, msgOrExpectedResultInfo)
.xtype(...)
: Same astype()
, but for an expected failure.indentFiles(dataDir)
: execute indentation on${dataDir}/*/origin
, compare with${dataDir}/*/expected
and write failure results in${dataDir}/*/actual
. If the${dataDir}/.kateconfig
file exists, it will be used for each test. Config variables (kate: ...
) can also be specified at the beginning and end of each test file.test(command, op: String, expected, msgOrInfo)
xtest(...)
: Same astest()
, but for an expected failure.eqvTrue(command, msgOrInfo)
eqvFalse(command, msgOrInfo)
eqTrue(command, msgOrInfo)
eqFalse(command, msgOrInfo)
error(command, expected, msgOrInfo)
errorMsg(command, expected, msgOrInfo)
errorType(command, expected, msgOrInfo)
hasError(command, msgOrInfo)
eqv(command, expected, msgOrInfo)
is(command, expected, msgOrInfo)
eq(command, expected, msgOrInfo)
ne(command, expected, msgOrInfo)
lt(command, expected, msgOrInfo)
gt(command, expected, msgOrInfo)
le(command, expected, msgOrInfo)
ge(command, expected, msgOrInfo)
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:55:25 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.