Skip to content

Commit

Permalink
Some new notepad messages added (#361)
Browse files Browse the repository at this point in the history
* add setUntitledName method

* add getTabColorID method

* add getNativeLangFileName method

* docu updates and fixes

* add get- and setLineNumberWidthMode methods

* add get-, setExternalLexerAutoIndentMode and isAutoIndention methods

* docu updates

* MENUCOMMAND enum related cleanups and docu updates

* fixes and new tests

* make FontStyle tests more robust and cleanups

* Skip ansi related test with PythonScript3 version

* docu update about correct rereplace usage
  • Loading branch information
Ekopalypse authored Dec 26, 2024
1 parent 1eca866 commit dfae4ba
Show file tree
Hide file tree
Showing 11 changed files with 675 additions and 164 deletions.
69 changes: 43 additions & 26 deletions PythonScript/python_tests/RunTests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,62 @@
import sys
import unittest
import os
from Npp import console, notepad, MESSAGEBOXFLAGS

# unittest module expects argv to be set
sys.argv = ['']
def main():

(path, runTestsName) = os.path.split(__file__)
# A debug build influences the test runs due to the assertions and print outputs.
if notepad.messageBox(
"Make sure you have a release build of the PythonScript plugin if you want to run the test suite.\n\nShould the test suite be started?",
"Run Tests?",
MESSAGEBOXFLAGS.ICONQUESTION | MESSAGEBOXFLAGS.YESNO
) == MESSAGEBOXFLAGS.RESULTNO:
return

test_suites = []
# unittest module expects argv to be set
sys.argv = ['']

results = unittest.TestResult()
loader = unittest.TestLoader()
test_suites = loader.discover(os.path.join(path, 'tests'))
(path, runTestsName) = os.path.split(__file__)

alltests = unittest.TestSuite(test_suites)
test_suites = []

console.show()
console.clear()
results = unittest.TestResult()
loader = unittest.TestLoader()
test_suites = loader.discover(os.path.join(path, 'tests'))

alltests.run(results)
alltests = unittest.TestSuite(test_suites)

# console.write('Tests Run: {} Errors: {} Failures: {}'.format(results.testRun, results.errors, results.failures))
console.clear()

def writeTestFailure(error):
console.write('TEST: %s\n' % error[0])
console.writeError(error[1])
console.write('\n----------------------------\n')

if results.errors:
for error in results.errors:
writeTestFailure(error)
alltests.run(results)

if results.failures:
for error in results.failures:
writeTestFailure(error)
# console.write('Tests Run: {} Errors: {} Failures: {}'.format(results.testRun, results.errors, results.failures))

def writeTestFailure(error):
console.write('TEST: %s\n' % error[0])
console.writeError(error[1])
console.write('\n----------------------------\n')

if results.errors:
for error in results.errors:
writeTestFailure(error)

if results.failures:
for error in results.failures:
writeTestFailure(error)

if results.errors or results.failures:
console.writeError('Tests Run: {} Errors: {} Failures: {}\n'.format(results.testsRun, len(results.errors), len(results.failures)))
else:
console.write('Tests Run: {} Errors: {} Failures: {}\n'.format(results.testsRun, len(results.errors), len(results.failures)))

if results.errors or results.failures:
console.writeError('Tests Run: {} Errors: {} Failures: {}\n'.format(results.testsRun, len(results.errors), len(results.failures)))
else:
console.write('Tests Run: {} Errors: {} Failures: {}\n'.format(results.testsRun, len(results.errors), len(results.failures)))
if results.skipped:
console.write('Skipped: {}\n'.format(len(results.skipped)))
for skipped_test in results.skipped:
console.write(' {} - {}\n'.format(skipped_test[0], skipped_test[1]))

console.show()


main()
152 changes: 129 additions & 23 deletions PythonScript/python_tests/tests/test_NotepadWrapperTestCase.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from threading import Timer
import subprocess

from Npp import notepad, editor, console, WINVER, LANGTYPE, MENUCOMMAND, BUFFERENCODING
from Npp import notepad, editor, console, WINVER, LANGTYPE, MENUCOMMAND, BUFFERENCODING, LINENUMWIDTHMODE

EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool,
ctypes.wintypes.HWND,
Expand Down Expand Up @@ -69,14 +69,11 @@ def _get_active_styler_xml(self):
darkmode_enabled = xml_doc.find('GUIConfigs/GUIConfig[@name="DarkMode"]').get('enable')
darkThemeName = xml_doc.find('GUIConfigs/GUIConfig[@name="DarkMode"]').get('darkThemeName')
lightThemeName = xml_doc.find('GUIConfigs/GUIConfig[@name="DarkMode"]').get('lightThemeName')
print(darkmode_enabled)
themepath = os.path.join(self._get_config_directory(), r'stylers.xml')
themepath = os.path.join(self._get_config_directory(), r'stylers.xml')
if(darkmode_enabled != 'no'):
print(darkThemeName)
themepath = os.path.join(self._get_config_directory(), r'themes', darkThemeName)
themepath = os.path.join(self._get_config_directory(), r'themes', darkThemeName)
elif(lightThemeName != ''):
print(lightThemeName)
themepath = os.path.join(self._get_config_directory(), r'themes', lightThemeName)
themepath = os.path.join(self._get_config_directory(), r'themes', lightThemeName)
return themepath


Expand Down Expand Up @@ -447,26 +444,28 @@ def store_silent_updates(hwnd, lParam):
f.close()
beforeReload = editor.getText()
# TODO: See https://github.com/notepad-plus-plus/notepad-plus-plus/issues/12418
self.assertFalse(notepad.reloadFile(filename, False))
self.assertTrue(notepad.reloadFile(filename, False))
afterReload = editor.getText()
notepad.close()

self.assertEqual(beforeReload, 'Reload test')
self.assertEqual(afterReload, 'Updated outside')

def test_getPluginConfigDir(self):
dir = notepad.getPluginConfigDir()
self.assertTrue(dir.lower().endswith('plugins\\config'))
cur_dir = notepad.getPluginConfigDir()
self.assertTrue(cur_dir.lower().endswith('plugins\\config'))


def test_nppCommandLineDir(self):
dir = notepad.getNppDir()
cur_dir = notepad.getNppDir()
commandLine = notepad.getCommandLine()

nppExe = shlex.split(commandLine)[0]
nppExe = shlex.split(commandLine, posix=False)[0]
nppDirOfExe = os.path.dirname(nppExe)

self.assertEqual(dir, nppDirOfExe)
if nppDirOfExe:
self.assertEqual(cur_dir, nppDirOfExe, msg="Expected same value, got: {} vs. {}".format(cur_dir, nppDirOfExe))
else:
self.assertTrue(len(commandLine) != 0)


# new tests
Expand Down Expand Up @@ -1501,7 +1500,8 @@ def start_monitor():

menu_handle = ctypes.windll.user32.SendMessageW(tabbar_context_menu_hwnd, MN_GETHMENU, 0, 0)
item_count = ctypes.windll.user32.GetMenuItemCount(menu_handle)
self.assertEqual(item_count, 16, msg=u'Expected 16 menu items but received:{}'.format(item_count))
# TODO: a hard-coded value is quite bad
self.assertEqual(item_count, 17, msg=u'Expected 17 menu items but received:{}'.format(item_count))
ctypes.windll.user32.SendMessageW(tabbar_context_menu_hwnd, WM_CLOSE, 0, 0)

timer = Timer(1, start_monitor)
Expand All @@ -1515,14 +1515,123 @@ def test_getPluginHomePath(self):
_, _, plugin_dir = notepad.getPluginHomePath().rpartition('\\')
self.assertTrue('plugins' == plugin_dir)


def test_getSettingsOnCloudPath(self):
''' Check if cloud path last part has default empty '''
self.__test_invalid_parameter_passed(notepad.getSettingsOnCloudPath)
_, _, cloud_dir = notepad.getSettingsOnCloudPath().rpartition('\\')
self.assertTrue('' == cloud_dir)


def test_setUntitledName(self):
''' '''
notepad_method = notepad.setUntitledName
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, None,None)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, None,None,None)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, -1)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, -1,-1,-1)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, '','')


def test_getTabColorID(self):
''' '''
notepad_method = notepad.getTabColorID
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, None)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, None,None)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, None,None,None)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, -1,-1,-1)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, '','')
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, '42','42')

# first get the configured colors
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_NONE)
tab_colour_none = notepad.getTabColorID()
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_1)
tab_color_1 = notepad.getTabColorID()
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_2)
tab_color_2 = notepad.getTabColorID()
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_3)
tab_color_3 = notepad.getTabColorID()
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_4)
tab_color_4 = notepad.getTabColorID()
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_5)
tab_color_5 = notepad.getTabColorID()

# test
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_NONE)
self.assertTrue(tab_colour_none == notepad.getTabColorID())
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_1)
self.assertTrue(tab_color_1== notepad.getTabColorID())
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_2)
self.assertTrue(tab_color_2== notepad.getTabColorID())
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_3)
self.assertTrue(tab_color_3== notepad.getTabColorID())
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_4)
self.assertTrue(tab_color_4== notepad.getTabColorID())
notepad.menuCommand(MENUCOMMAND.VIEW_TAB_COLOUR_5)
self.assertTrue(tab_color_5== notepad.getTabColorID())


def test_getNativeLangFileName(self):
''' '''
self.__test_invalid_parameter_passed(notepad.getNativeLangFileName)


def test_lineNumberWidthMode(self):
''' '''
self.__test_invalid_parameter_passed(notepad.getLineNumberWidthMode)
self.__test_invalid_parameter_passed(notepad.setLineNumberWidthMode)

mode = notepad.getLineNumberWidthMode()
if notepad.setLineNumberWidthMode(LINENUMWIDTHMODE.CONSTANT if mode == LINENUMWIDTHMODE.DYNAMIC else LINENUMWIDTHMODE.DYNAMIC):
changed_mode = notepad.getLineNumberWidthMode()
self.assertTrue(changed_mode != mode, msg="Expected different modes, got {} and {}".format(mode, changed_mode))
if notepad.setLineNumberWidthMode(LINENUMWIDTHMODE.CONSTANT if mode == LINENUMWIDTHMODE.CONSTANT else LINENUMWIDTHMODE.DYNAMIC):
revert_changed_mode = notepad.getLineNumberWidthMode()
self.assertTrue(revert_changed_mode == mode, msg="Expected same modes, got {} and {}".format(mode, changed_mode))

# TODO: How can this be tested in a meaningful way?
def test_getExternalLexerAutoIndentMode(self):
''' '''
notepad_method = notepad.getExternalLexerAutoIndentMode
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, None,None)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, None,None,None)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, -1)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, -1,-1,-1)
with self.assertRaises(ArgumentError):
self._invalid_parameter_passed(notepad_method, '','')

# TODO: How can this be tested in a meaningful way?
def test_setExternalLexerAutoIndentMode(self):
''' '''
self.__test_invalid_parameter_passed(notepad.setExternalLexerAutoIndentMode)

# TODO: How can this be tested in a meaningful way?
def test_isAutoIndention(self):
''' '''
self.__test_invalid_parameter_passed(notepad.isAutoIndention)


suite = unittest.TestLoader().loadTestsFromTestCase(NotepadTestCase)

if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(NotepadTestCase)
alltests = unittest.TestSuite(suite)

results = unittest.TestResult()
Expand All @@ -1545,10 +1654,7 @@ def writeTestFailure(error):
console.writeError('Tests Run: {}\n Errors : {}\n Failures: {}\n'.format(results.testsRun, len(results.errors), len(results.failures)))
else:
console.write('Tests Run: {}\n Errors : {}\n Failures: {}\n'.format(results.testsRun, len(results.errors), len(results.failures)))
if results.skipped:
console.write('Skipped: {}\n'.format(len(results.skipped)))
for skipped_test in results.skipped:
console.write(' {} - {}\n'.format(skipped_test[0], skipped_test[1]))
console.show()
else:
suite = unittest.TestLoader().loadTestsFromTestCase(NotepadTestCase)
if results.skipped:
console.write('Skipped: {}\n'.format(len(results.skipped)))
for skipped_test in results.skipped:
console.write(' {} - {}\n'.format(skipped_test[0], skipped_test[1]))
20 changes: 13 additions & 7 deletions PythonScript/python_tests/tests/test_ReplaceAnsiPythonFunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ def tearDown(self):
editor.setSavePoint()
notepad.close()

@unittest.skipIf(notepad.getPluginVersion()[0] == '3', "not yet py3-compatible")
def test_replace_function(self):
editor.rereplace(r'([a-z]+)([0-9]+)'.encode('windows-1252'), group2_with_counter)
text = editor.getText()
self.assertEqual(text, u'1231 54322 983\r\nä1234 ü54325 ö986\r\n'.encode('windows-1252'))

@unittest.skipIf(notepad.getPluginVersion()[0] == '3', "not yet py3-compatible")
def test_unicode_replace_function(self):
editor.rereplace(ur'([a-zäöü]+)([0-9]+)', group1_with_counter)
editor.rereplace(r'([a-zäöü]+)([0-9]+)', group1_with_counter)
text = editor.getText()
self.assertEqual(text, u'abc1 def2 gh3\r\näbc4 üef5 öh6\r\n'.encode('windows-1252'))

Expand All @@ -55,24 +57,27 @@ def groups_check(self, m):
self.assertEqual(m.groups(), groups_data_correct[counter])
return counter

@unittest.skipIf(notepad.getPluginVersion()[0] == '3', "not yet py3-compatible")
def test_groups(self):
editor.rereplace(ur'([a-zäöü]+)([0-9]+)', lambda m: self.groups_check(m))
editor.rereplace(r'([a-zäöü]+)([0-9]+)', lambda m: self.groups_check(m))
text = editor.getText()
self.assertEqual(text, '1 2 3\r\n4 5 6\r\n')


@unittest.skipIf(notepad.getPluginVersion()[0] == '3', "not yet py3-compatible")
def test_groups_with_named_groups(self):
editor.rereplace(ur'(?<letters>[a-zäöü]+)(?<numbers>[0-9]+)', lambda m: self.groups_check(m))
editor.rereplace(r'(?<letters>[a-zäöü]+)(?<numbers>[0-9]+)', lambda m: self.groups_check(m))
text = editor.getText()
self.assertEqual(text, '1 2 3\r\n4 5 6\r\n')

@unittest.skipIf(notepad.getPluginVersion()[0] == '3', "not yet py3-compatible")
def test_named_groups(self):
editor.rereplace(ur'(?<letters>[a-zäöü]+)(?<numbers>[0-9]+)', lambda m: m.group('letters'))
editor.rereplace(r'(?<letters>[a-zäöü]+)(?<numbers>[0-9]+)', lambda m: m.group('letters'))
text = editor.getText()
self.assertEqual(text, u'abc def gh\r\näbc üef öh\r\n'.encode('windows-1252'))

@unittest.skipIf(notepad.getPluginVersion()[0] == '3', "not yet py3-compatible")
def test_named_groups_2(self):
editor.rereplace(ur'(?<letters>[a-zäöü]+)(?<numbers>[0-9]+)', lambda m: m.group('numbers'))
editor.rereplace(r'(?<letters>[a-zäöü]+)(?<numbers>[0-9]+)', lambda m: m.group('numbers'))
text = editor.getText()
self.assertEqual(text, '123 5432 98\r\n123 5432 98\r\n')

Expand All @@ -89,8 +94,9 @@ def group_tuples_check(self, m):
self.assertEqual(m.group(2, 'letters', 'numbers'), groups_data_correct[counter])
return counter

@unittest.skipIf(notepad.getPluginVersion()[0] == '3', "not yet py3-compatible")
def test_group_tuples(self):
editor.rereplace(ur'(?<letters>[a-zäöü]+)(?<numbers>[0-9]+)', lambda m: self.group_tuples_check(m))
editor.rereplace(r'(?<letters>[a-zäöü]+)(?<numbers>[0-9]+)', lambda m: self.group_tuples_check(m))
text = editor.getText()
self.assertEqual(text, '1 2 3\r\n4 5 6\r\n')

Expand Down
Loading

0 comments on commit dfae4ba

Please sign in to comment.