Compare commits

..

10 Commits

Author SHA1 Message Date
f513358236 LayoutManager: respect WITH_WEBENGINE flag
This patch updates LayoutManager to use WebEngine only
when WITH_WEBENGINE is set to true.

Change-Id: Idcfc99af9fb4d74c68aac8fc9029cde2bc05b4eb
2025-07-18 14:10:39 -04:00
3c00829afb packaging: use new icon filename
Follow-up to commit 5c772960bc.

Change-Id: Ib5c0b4bc1c5e3f5112bbd49bf323aeb4cc87c75e
2025-07-18 13:30:23 -04:00
84a59889e3 tests/qml: fix undefined references to appWindow
GitLab: #1780
Change-Id: I166f68c7abdf0f21d8d5dcec85e377c27de798a3
2025-07-16 16:17:16 -04:00
6c35561817 Reinstate "cmake: Simplify lookup logic for libjami headers." (again).
This reinstates commit f6c8197cba, which was seemingly reverted by
mistake in 4d2c55348b ("packaging: migrate from Qt 6.2.3 to
6.4.3").

Change-Id: I603e004431be0503be0acdd7ce37fa5aaa4ecd91
2025-07-16 12:58:01 -04:00
6ffdda7b81 tests: Fix WITH_WEBENGINE check.
Use #if, not #ifdef, to test the integer value of WITH_WEBENGINE, not
just whether it's defined.  Otherwise, -DWITH_WEBENGINE=OFF would not
work.

* tests/qml/main.cpp: Replace '#ifdef WITH_WEBENGINE' with '#if
WITH_WEBENGINE'.

Change-Id: Ieda8c46fa696afa1e4118acc7d4fecd4b7f9a171
2025-07-16 12:03:56 -04:00
a51078c900 tests: Avoid takeFirst-caused segfaults on empty arrays.
Replace EXPECT_EQ with ASSERT_EQ where a failure should be
fatal (abort execution).

Relates-to: <https://git.jami.net/savoirfairelinux/jami-client-qt/-/issues/1507>.
Change-Id: I4b5e38cdc399c1d1a51f72abab23cce963578541
2025-07-16 11:59:26 -04:00
76a710e2ab Fix running tests when building out of the source tree.
CMake's enable_testing needs to be called from the root of the project
as well for CTest to discover the tests in the build tree.  This is
covered in CMake's manual in section 7.2.17 enable_testing.

Change-Id: I7c9b845c52064ff83e39b483b76137b529c1a9a4
2025-07-16 11:57:28 -04:00
bc324aa8bb build: update guix manifest for build.py
Change-Id: I878ad4b2ae4adee4ebc623e4ab40362fd9e1034a
2025-07-16 11:56:55 -04:00
5c772960bc Adhere to flatpak/flathub requirements
- Developer id must be rDns identifier of developer
- Exported icons should match rDNS of app id
- Release version and dates should be included
- Added light and dark branding colours for Flathub banner
- Contact url removed - does not pass appstream validation

Change-Id: Ic5e2a5abeab4310ea87a34cc81363d1851135bcd
2025-07-16 11:31:12 -04:00
da2acefced packaging: add AlmaLinux 10
GitLab: #2065
Change-Id: I4252e2c128f72b3f6a78204a4134374b44155b80
2025-07-14 16:58:06 -04:00
33 changed files with 441 additions and 281 deletions

View File

@ -244,7 +244,7 @@ set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH} "${EXTRAS_DIR}/build/cmake/modules")
find_package(LibJami REQUIRED)
if(LIBJAMI_FOUND)
include_directories(${LIBJAMI_INCLUDE_DIRS})
include_directories(${LIBJAMI_INCLUDE_DIR})
endif()
include(FindPython3)
@ -847,12 +847,12 @@ elseif (NOT APPLE)
# Logos
install(
FILES resources/images/jami.svg
FILES resources/images/net.jami.Jami.svg
DESTINATION
${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps)
install(
FILES resources/images/jami-48px.png
FILES resources/images/net.jami.Jami-48px.png
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps
RENAME jami.png)
@ -1030,5 +1030,6 @@ qt_finalize_executable(${PROJECT_NAME})
# tests
if(BUILD_TESTING)
message("Add Jami tests")
enable_testing()
add_subdirectory(${TESTS_DIR})
endif()

View File

@ -16,30 +16,19 @@
# Once done, this find module will set:
#
# LIBJAMI_INCLUDE_DIRS - libjami include directories
# LIBJAMI_INCLUDE_DIR - libjami include directory
# LIBJAMI_FOUND - whether it was able to find the include directories
# LIBJAMI_LIB - path to libjami or libring library
set(LIBJAMI_FOUND true)
if(WITH_DAEMON_SUBMODULE)
set(LIBJAMI_INCLUDE_DIRS ${DAEMON_DIR}/src/jami)
set(LIBJAMI_INCLUDE_DIR ${DAEMON_DIR}/src/jami)
else()
if(EXISTS ${LIBJAMI_INCLUDE_DIR}/jami.h)
set(LIBJAMI_INCLUDE_DIRS ${LIBJAMI_INCLUDE_DIR})
elseif(EXISTS ${LIBJAMI_BUILD_DIR}/jami/jami.h)
set(LIBJAMI_INCLUDE_DIRS ${LIBJAMI_BUILD_DIR}/jami)
elseif(EXISTS ${RING_INCLUDE_DIR}/jami.h)
set(LIBJAMI_INCLUDE_DIRS ${RING_INCLUDE_DIR})
elseif(EXISTS ${RING_BUILD_DIR}/jami/jami.h)
set(LIBJAMI_INCLUDE_DIRS ${RING_BUILD_DIR}/jami)
elseif(EXISTS ${CMAKE_INSTALL_PREFIX}/include/jami/jami.h)
set(LIBJAMI_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include/jami)
elseif(EXISTS ${CMAKE_INSTALL_PREFIX}/daemon/include/jami/jami.h)
set(LIBJAMI_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/daemon/include/jami)
else()
find_path(LIBJAMI_INCLUDE_DIR jami.h PATH_SUFFIXES jami)
if(NOT LIBJAMI_INCLUDE_DIR)
message(STATUS "Jami daemon headers not found!
Set -DLIBJAMI_BUILD_DIR or -DCMAKE_INSTALL_PREFIX")
To build using the daemon git submodule, set -DWITH_DAEMON_SUBMODULE")
set(LIBJAMI_FOUND false)
endif()
endif()
@ -121,5 +110,5 @@ endif()
# Restore the original value of CMAKE_FIND_LIBRARY_SUFFIXES.
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_orig})
message(STATUS "Jami daemon headers are in " ${LIBJAMI_INCLUDE_DIRS})
message(STATUS "Jami daemon headers are in " ${LIBJAMI_INCLUDE_DIR})
message(STATUS "Jami daemon library is at " ${LIBJAMI_LIB})

View File

@ -85,7 +85,7 @@
<id>net.jami.daemon</id>
</requires>
<launchable type="desktop-id">net.jami.Jami.desktop</launchable>
<icon type="stock">jami</icon>
<icon type="stock">net.jami.Jami</icon>
<url type="homepage">https://jami.net/</url>
<url type="bugtracker">https://git.jami.net/savoirfairelinux/jami-client-qt/issues</url>
<url type="faq">https://docs.jami.net/user/faq.html</url>

View File

@ -4,7 +4,7 @@ GenericName=Jami
Comment=Share, freely and privately
Comment[hu]=Megosztás, szabadon és bizalmasan
Exec=jami %u
Icon=jami
Icon=net.jami.Jami
StartupNotify=true
Terminal=false
Type=Application

View File

@ -7,15 +7,26 @@
<summary>Share, freely and privately</summary>
<summary xml:lang="hu">Megosztás, szabadon és bizalmasan</summary>
<icon type="stock">jami</icon>
<icon type="stock">net.jami.Jami</icon>
<metadata_license>CC-BY-SA-3.0</metadata_license>
<project_license>GPL-3.0+</project_license>
<developer id="net.jami.Jami">
<developer id="net.jami">
<name>Savoir-faire Linux Inc.</name>
</developer>
<releases>
<release version="20250613.0" date="2025-06-13">
<url type="details">https://git.jami.net/savoirfairelinux/jami-client-qt/-/wikis/Changelog#nightlystable-20250613</url>
</release>
</releases>
<branding>
<color type="primary" scheme_preference="light">#03b9e9</color>
<color type="primary" scheme_preference="dark">#005699</color>
</branding>
<!-- https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-description -->
<description>
@ -76,7 +87,6 @@
<url type="bugtracker">https://git.jami.net/savoirfairelinux/jami-client-qt/issues</url>
<url type="homepage">https://jami.net/</url>
<url type="donation">https://jami.net/whydonate/</url>
<url type="contact">contact@jami.net</url>
<url type="faq">https://docs.jami.net/user/faq.html</url>
<url type="translate">https://explore.transifex.com/savoirfairelinux/jami/</url>
<url type="contribute">https://jami.net/contribute/</url>

View File

@ -172,6 +172,7 @@ DISTRIBUTIONS := \
fedora_41 \
fedora_42 \
alma_9 \
alma_10 \
opensuse-leap_15.6 \
snap
@ -251,7 +252,7 @@ define guix-pack-command
guix pack -C xz -f $(1) -m $(CURDIR)/extras/packaging/gnu-linux/guix/guix-pack-manifest.scm -v3 \
-S /usr/bin/jami=bin/jami \
-S /usr/share/applications/net.jami.Jami.desktop=share/applications/net.jami.Jami.desktop \
-S /usr/share/icons/hicolor/scalable/apps/jami.svg=share/icons/hicolor/scalable/apps/jami.svg \
-S /usr/share/icons/hicolor/scalable/apps/net.jami.Jami.svg=share/icons/hicolor/scalable/apps/net.jami.Jami.svg \
-S /usr/share/icons/hicolor/48x48/apps/jami.png=share/icons/hicolor/48x48/apps/jami.png \
-S /usr/share/metainfo/net.jami.Jami.metainfo.xml=share/metainfo/net.jami.Jami.metainfo.xml \
-S /usr/share/swcatalog/xml/jami.xml=share/swcatalog/xml/jami.xml \

View File

@ -0,0 +1,93 @@
FROM almalinux:10
RUN dnf clean all && dnf update -y
RUN dnf install -y epel-release
RUN dnf install -y 'dnf-command(config-manager)'
RUN dnf config-manager --set-enabled crb
RUN dnf config-manager --set-enabled appstream
RUN dnf install -y dnf-command\(builddep\) rpmdevtools && \
dnf install -y mock
RUN yum install -y xorg-x11-xauth
RUN dnf install -y \
alsa-lib-devel \
astyle \
autoconf \
automake \
bison \
check \
chrpath \
clang15-devel \
cmake \
cryptopp-devel \
cups-devel \
dbus-devel \
expat-devel \
flex \
fmt-devel \
gcc-c++ \
gettext-devel \
git \
gnutls-devel \
gperf \
gsm-devel \
gstreamer1 gstreamer1-devel \
gstreamer1-plugins-bad-free-devel \
gstreamer1-plugins-base-devel \
gstreamer1-plugins-good \
jsoncpp-devel \
libX11-devel \
libXext-devel \
libXfixes-devel \
libXrender-devel \
libappindicator-gtk3-devel \
libargon2-devel \
libcanberra-devel \
libcurl-devel \
libdrm \
libnatpmp-devel \
libnotify \
libnotify-devel \
libsndfile-devel \
libstdc++-static \
libtool \
libupnp-devel \
libuuid-devel \
libva-devel \
libvdpau-devel \
libxcb* \
libxkb* \
libxshmfence-devel \
llvm15-devel \
make \
mesa-dri-drivers \
mesa-libgbm-devel \
msgpack-devel \
nasm \
nettle-devel \
NetworkManager-libnm-devel \
ninja-build \
nodejs \
nss-devel \
openssl-devel \
opus-devel \
pcre2-devel \
perl-English \
perl-generators \
pipewire-devel \
pulseaudio-libs-devel \
python3-html5lib \
qrencode-devel \
speex-devel \
speexdsp-devel \
sqlite-devel \
systemd-devel \
uuid-devel \
vulkan-devel \
webkitgtk6.0-devel \
wget \
which \
xcb-util-* \
xkeyboard-config \
yaml-cpp-devel \
yasm
ADD extras/packaging/gnu-linux/scripts/build-package-rpm.sh /opt/build-package-rpm.sh
CMD ["/opt/build-package-rpm.sh"]

View File

@ -24,7 +24,10 @@
(list
;; Minimal requirements of the daemon contrib build system.
"coreutils"
"gcc-toolchain"
;; When using GCC 15, Jami fails to link with errors like:
;; ld: CMakeFiles/jami.dir/src/app/main.cpp.o:(.rodata+0x0):
;; multiple definition of `QtPrivate::IsFloatType_v<_Float16>'
"gcc-toolchain@14"
"git-minimal"
"grep"
"gzip"
@ -42,18 +45,12 @@
"alsa-lib"
"autoconf"
"automake"
"asio"
"bash"
"bzip2"
"cmake"
"dbus"
;; Bundled because broken with GCC 7 upstream (unmaintained). When
;; attempting to use it, it would cause confusing errors such as
;; "ld: ../src/.libs/libring.a(libupnpcontrol_la-upnp_context.o): in
;; function `jami::upnp::UPnPContext::updateMappingList(bool)':
;; upnp_context.cpp:(.text+0xa4be): undefined reference to
;; `std::__cxx11::basic_ostringstream<char, std::char_traits<char>,
;; std::allocator<char> >::basic_ostringstream()'
;;"dbus-c++" ;for dbusxx-xml2cpp
;;"dhtnet" ;bundled because tightly coupled
"diffutils"
"doxygen"
"eudev" ;udev library
@ -67,6 +64,7 @@
"gsm"
"gtk-doc"
"http-parser"
"jack@0"
"jsoncpp"
"libarchive"
"libgit2"
@ -84,16 +82,24 @@
"patch"
"pcre"
"perl"
"pipewire"
;;"pjproject" ;bundled because patched
"pulseaudio"
"sdbus-c++@1"
"speex"
"speexdsp"
"webrtc-audio-processing@0"
"which"
"yaml-cpp"
"yasm"
;; For the Qt client.
"glib"
"hunspell"
"libnotify"
"libxcb"
"libxkbcommon"
"md4c"
"network-manager" ;libnm
"qrencode"
"qtbase"
@ -103,10 +109,13 @@
"qtnetworkauth"
"qtpositioning"
"qtsvg"
"qwindowkit"
"qttools"
"qtwebchannel"
"qtwebengine"
"tidy-html"
"vulkan-headers"
"zxing-cpp"
;; For tests and debugging.
"file"

View File

@ -49,7 +49,7 @@ BuildRequires: libXfixes-devel
BuildRequires: libuuid-devel
BuildRequires: libva-devel
BuildRequires: libvdpau-devel
BuildRequires: pcre-devel
BuildRequires: (pcre-devel or pcre2-devel)
BuildRequires: pipewire-devel
BuildRequires: uuid-devel
BuildRequires: yaml-cpp-devel

View File

@ -31,6 +31,7 @@ URL: https://jami.net/
Source: jami-libqt-%{version}.tar.xz
Patch0: 0001-fix-gcc14.patch
Patch1: 0002-qtwebengine-add-missing-chromium-dependencies.patch
Patch2: 0003-fix-embree-linking-errors.patch
%global gst 0.10
%if 0%{?fedora} || 0%{?rhel} > 7
@ -68,6 +69,7 @@ This package contains Qt libraries for Jami.
%setup -n qt-everywhere-src-%{version}
%patch -P 0 -p1
%patch -P 1 -p1
%patch -P 2 -p1
%build
echo "Building Qt using %{job_count} parallel jobs"

View File

@ -85,7 +85,7 @@ DESTDIR=%{buildroot} make -C %{_builddir}/jami-%{version}/build install V=2
%{_bindir}/jami
%{_datadir}/applications/net.jami.Jami.desktop
%{_datadir}/jami/net.jami.Jami.desktop
%{_datadir}/icons/hicolor/scalable/apps/jami.svg
%{_datadir}/icons/hicolor/scalable/apps/net.jami.Jami.svg
%{_datadir}/icons/hicolor/48x48/apps/jami.png
%{_datadir}/pixmaps/jami.xpm
%{_datadir}/metainfo/net.jami.Jami.metainfo.xml

View File

@ -0,0 +1,29 @@
From 709d0b0cf45b920f63960a70725138dbaf7ec721 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois-Simon=20Fauteux-Chapleau?=
<francois-simon.fauteux-chapleau@savoirfairelinux.com>
Date: Wed, 18 Jun 2025 15:53:55 -0400
Subject: [PATCH] Fix embree linking errors
Patch taken from:
https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=37bd373cd33c36f8dd44e71be25fa6ea24cf4588
---
qtquick3d/src/3rdparty/embree/CMakeLists.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/qtquick3d/src/3rdparty/embree/CMakeLists.txt b/qtquick3d/src/3rdparty/embree/CMakeLists.txt
index cf27196de2..332bbd17ca 100644
--- a/qtquick3d/src/3rdparty/embree/CMakeLists.txt
+++ b/qtquick3d/src/3rdparty/embree/CMakeLists.txt
@@ -62,6 +62,9 @@ if (IOS)
endif()
# Use SSE2 only, ignore AVX/SSE4.2 for now
+if (TEST_architecture_arch STREQUAL x86_64)
+ qt_internal_extend_target(BundledEmbree COMPILE_OPTIONS -mno-avx -mno-sse4.2)
+endif()
qt_internal_extend_target(BundledEmbree DEFINES
EMBREE_TARGET_SSE2
__SSE2__
--
2.34.1

View File

@ -270,7 +270,7 @@ parts:
ls
snapcraftctl pull
sed -i -E 's|(tmpName) << (PACKAGE_NAME << "_shm_")|\1 << "snap.jami." << \2|' ./daemon/src/media/video/sinkclient.cpp
sed -i -E 's|^Icon=.*|Icon=${SNAP}/usr/share/icons/hicolor/scalable/apps/jami.svg|' extras/data/net.jami.Jami.desktop
sed -i -E 's|^Icon=.*|Icon=${SNAP}/usr/share/icons/hicolor/scalable/apps/net.jami.Jami.svg|' extras/data/net.jami.Jami.desktop
override-build: |
$SNAPCRAFT_PART_BUILD/extras/packaging/gnu-linux/scripts/install-pipewire-from-source.sh

View File

@ -107,6 +107,8 @@ if [ ! -f "${RPM_PATH}" ]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc42.x86_64.rpm "${RPM_PATH}"
elif [[ "${DISTRIBUTION}" == "alma_9" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.el9.x86_64.rpm "${RPM_PATH}"
elif [[ "${DISTRIBUTION}" == "alma_10" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.el10.x86_64.rpm "${RPM_PATH}"
else
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-*.rpm "${RPM_PATH}"
fi

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -17,7 +17,6 @@
import QtQuick
import QtQuick.Controls
import QtWebEngine
import net.jami.Adapters 1.1
import net.jami.Enums 1.1
@ -253,9 +252,15 @@ QtObject {
isCallFullscreen = fullScreenItems
.filter(o => o.item.objectName === "callViewLoader")
.length
isWebFullscreen = fullScreenItems
.filter(o => o.item instanceof WebEngineView)
.length
isWebFullscreen = WITH_WEBENGINE ? fullScreenItems
.filter(o => o.item && (
o.item.objectName === JamiQmlUtils.webEngineNames.mediaPreview ||
o.item.objectName === JamiQmlUtils.webEngineNames.videoPreview ||
o.item.objectName === JamiQmlUtils.webEngineNames.map ||
o.item.objectName === JamiQmlUtils.webEngineNames.general ||
o.item.objectName === JamiQmlUtils.webEngineNames.emojiPicker
))
.length : 0
}
// Listen for a hangup combined with a fullscreen call state and

View File

@ -464,7 +464,7 @@ MainApplication::initQmlLayer()
void
MainApplication::initSystray()
{
systemTray_->setIcon(QIcon(":/images/jami.svg"));
systemTray_->setIcon(QIcon(":/images/net.jami.Jami.svg"));
QMenu* menu {nullptr};
// If there was a previous menu, reuse it, otherwise create a new one.

View File

@ -25,6 +25,14 @@ Item {
property string qmlFilePrefix: "file:/"
readonly property string base64StringTitle: "data:image/png;base64,"
readonly property var webEngineNames: {
"mediaPreview": "mediaPreviewWebEngine",
"videoPreview": "videoPreviewWebEngine",
"map": "mapWebEngine",
"general": "generalWebEngine",
"emojiPicker": "emojiPickerWebEngine"
}
property var accountCreationInputParaObject: ({})
function setUpAccountCreationInputPara(inputPara) {

View File

@ -146,7 +146,7 @@ void
SystemTray::onNotificationCountChanged(int count)
{
if (count == 0) {
setIcon(QIcon(":/images/jami.svg"));
setIcon(QIcon(":/images/net.jami.Jami.svg"));
} else {
setIcon(QIcon(":/images/jami-new.svg"));
}
@ -258,9 +258,9 @@ SystemTray::showNotification(const QString& message,
setOnClickedCallback(std::move(onClickedCb));
if (from.isEmpty())
showMessage(message, "", QIcon(":images/jami.svg"));
showMessage(message, "", QIcon(":images/net.jami.Jami.svg"));
else
showMessage(from, message, QIcon(":images/jami.svg"));
showMessage(from, message, QIcon(":images/net.jami.Jami.svg"));
}
template<typename Func>

View File

@ -22,6 +22,7 @@ import net.jami.Constants 1.1
WebEngineView {
id: root
objectName: JamiQmlUtils.webEngineNames.general
property string onCompletedLoadHtml: ""
property string onCompletedUrl: "qrc" + onCompletedLoadHtml

View File

@ -26,6 +26,7 @@ import "../commoncomponents"
WebEngineView {
id: wev
objectName: JamiQmlUtils.webEngineNames.mediaPreview
property bool isVideo
property string html
readonly property real minSize: 192

View File

@ -28,6 +28,7 @@ Rectangle {
WebEngineView {
id: wev
objectName: JamiQmlUtils.webEngineNames.videoPreview
anchors.fill: parent
anchors.verticalCenter: root.verticalCenter

View File

@ -77,6 +77,7 @@ Popup {
GeneralWebEngineView {
id: emojiPickerWebView
objectName: JamiQmlUtils.webEngineNames.emojiPicker
width: JamiTheme.emojiPickerWidth
height: JamiTheme.emojiPickerHeight

View File

@ -132,6 +132,7 @@ Item {
WebEngineView {
id: webView
objectName: JamiQmlUtils.webEngineNames.map
layer.enabled: !isFullScreen
layer.effect: OpacityMask {

View File

@ -48,7 +48,7 @@ set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH} "${EXTRAS_DIR}/build/cmake/modules")
find_package(LibJami REQUIRED)
if(LIBJAMI_FOUND)
include_directories(${LIBJAMI_INCLUDE_DIRS})
include_directories(${LIBJAMI_INCLUDE_DIR})
endif()
string(SUBSTRING ${CMAKE_GENERATOR} 0 14 CMAKE_GENERATOR_SHORT)

View File

@ -39,7 +39,7 @@ else()
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${LIBJAMI_INCLUDE_DIRS})
include_directories(${LIBJAMI_INCLUDE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../dbus)

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)
enable_testing(true)
enable_testing()
set(QT_TESTING_MODULES
${QT_MODULES}

View File

@ -35,7 +35,7 @@
#include <QtQuickTest/quicktest.h>
#include <QSignalSpy>
#ifdef WITH_WEBENGINE
#if WITH_WEBENGINE
#include <QtWebEngineCore>
#include <QtWebEngineQuick>
#endif
@ -206,7 +206,7 @@ main(int argc, char** argv)
// Allow the user to enable fatal warnings for certain tests.
Utils::remove_argument(argv, argc, "--failonwarn", [&]() { qputenv("QT_FATAL_WARNINGS", "1"); });
#ifdef WITH_WEBENGINE
#if WITH_WEBENGINE
QtWebEngineQuick::initialize();
#endif
QTEST_SET_MAIN_SOURCE_PATH

View File

@ -28,34 +28,36 @@ import "../../../src/app/mainview"
import "../../../src/app/mainview/components"
import "../../../src/app/commoncomponents"
ListSelectionView {
id: viewNode
objectName: "ConversationView"
managed: false
TestWrapper {
ListSelectionView {
id: viewNode
objectName: "ConversationView"
managed: false
leftPaneItem: Rectangle {}
leftPaneItem: Rectangle {}
rightPaneItem: ChatView {
id: uut
rightPaneItem: ChatView {
id: uut
inCallView: false
inCallView: false
TestCase {
name: "Check basic visibility for header buttons"
function test_checkBasicVisibility() {
var chatviewHeader = findChild(uut, "chatViewHeader")
var detailsButton = findChild(chatviewHeader, "detailsButton")
compare(detailsButton.visible, true)
TestCase {
name: "Check basic visibility for header buttons"
function test_checkBasicVisibility() {
var chatviewHeader = findChild(uut, "chatViewHeader")
var detailsButton = findChild(chatviewHeader, "detailsButton")
compare(detailsButton.visible, true)
var chatViewFooter = findChild(uut, "chatViewFooter")
CurrentConversation.isTemporary = true
compare(chatViewFooter.visible, true)
CurrentConversation.isTemporary = false
CurrentConversation.isRequest = true
compare(chatViewFooter.visible, false)
CurrentConversation.isRequest = false
CurrentConversation.needsSyncing = true
compare(chatViewFooter.visible, false)
var chatViewFooter = findChild(uut, "chatViewFooter")
CurrentConversation.isTemporary = true
compare(chatViewFooter.visible, true)
CurrentConversation.isTemporary = false
CurrentConversation.isRequest = true
compare(chatViewFooter.visible, false)
CurrentConversation.isRequest = false
CurrentConversation.needsSyncing = true
compare(chatViewFooter.visible, false)
}
}
}
}

View File

@ -26,40 +26,42 @@ import net.jami.Enums 1.1
import "../../../src/app/settingsview"
import "../../../src/app/commoncomponents"
SettingsSidePanel {
id: uut
TestWrapper {
SettingsSidePanel {
id: uut
SignalSpy {
id: spyUpdated
SignalSpy {
id: spyUpdated
target: uut
signalName: "updated"
}
SignalSpy {
id: spyChangeLang
target: UtilsAdapter
signalName: "changeLanguage"
}
TestCase {
name: "WelcomePage to different account creation page and return back"
when: windowShown
function test_retranslate() {
spyUpdated.clear()
UtilsAdapter.setAppValue(Settings.Key.LANG, "en_EN")
spyChangeLang.wait(1000)
compare(spyChangeLang.count, 1)
spyUpdated.wait(1000)
compare(spyUpdated.count, 1)
UtilsAdapter.setAppValue(Settings.Key.LANG, "fr")
spyChangeLang.wait(1000)
compare(spyChangeLang.count, 2)
spyUpdated.wait(1000)
compare(spyUpdated.count, 2)
target: uut
signalName: "updated"
}
}
SignalSpy {
id: spyChangeLang
target: UtilsAdapter
signalName: "changeLanguage"
}
TestCase {
name: "WelcomePage to different account creation page and return back"
when: windowShown
function test_retranslate() {
spyUpdated.clear()
UtilsAdapter.setAppValue(Settings.Key.LANG, "en_EN")
spyChangeLang.wait(1000)
compare(spyChangeLang.count, 1)
spyUpdated.wait(1000)
compare(spyUpdated.count, 1)
UtilsAdapter.setAppValue(Settings.Key.LANG, "fr")
spyChangeLang.wait(1000)
compare(spyChangeLang.count, 2)
spyUpdated.wait(1000)
compare(spyUpdated.count, 2)
}
}
}
}

View File

@ -26,192 +26,194 @@ import net.jami.Enums 1.1
import "../../../src/app/wizardview"
import "../../../src/app/commoncomponents"
WizardView {
id: uut
TestWrapper {
WizardView {
id: uut
width: 400
height: 600
width: 400
height: 600
function clearSignalSpy() {
spyAccountIsReady.clear()
spyAccountIsRemoved.clear()
spyAccountConfigFinalized.clear()
spyReportFailure.clear()
spyCloseWizardView.clear()
function clearSignalSpy() {
spyAccountIsReady.clear()
spyAccountIsRemoved.clear()
spyAccountConfigFinalized.clear()
spyReportFailure.clear()
spyCloseWizardView.clear()
spyBackButtonVisible.target = undefined
}
SignalSpy {
id: spyAccountIsReady
target: WizardViewStepModel
signalName: "accountIsReady"
}
SignalSpy {
id: spyAccountIsRemoved
target: AccountAdapter
signalName: "accountRemoved"
}
SignalSpy {
id: spyAccountStatusChanged
target: AccountAdapter
signalName: "accountStatusChanged"
}
SignalSpy {
id: spyAccountConfigFinalized
target: AccountAdapter
signalName: "accountConfigFinalized"
}
SignalSpy {
id: spyReportFailure
target: AccountAdapter
signalName: "reportFailure"
}
SignalSpy {
id: spyCloseWizardView
target: WizardViewStepModel
signalName: "closeWizardView"
}
SignalSpy {
id: spyBackButtonVisible
signalName: "visibleChanged"
}
TestCase {
name: "WelcomePage to different account creation page and return back"
when: windowShown
function test_welcomePageStepInStepOut() {
var controlPanelStackView = findChild(uut, "controlPanelStackView")
var welcomePage = findChild(uut, "welcomePage")
var createAccountPage = findChild(uut, "createAccountPage")
var importFromDevicePage = findChild(uut, "importFromDevicePage")
var importFromBackupPage = findChild(uut, "importFromBackupPage")
var connectToAccountManagerPage = findChild(uut, "connectToAccountManagerPage")
var createSIPAccountPage = findChild(uut, "createSIPAccountPage")
// Go to createAccount page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.CreateJamiAccount)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
createAccountPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to CreateRendezVous page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.CreateRendezVous)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
createAccountPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to CreateRendezVous page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.ImportFromDevice)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
importFromDevicePage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to ImportFromBackup page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.ImportFromBackup)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
importFromBackupPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to ConnectToAccountManager page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.ConnectToAccountManager)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
connectToAccountManagerPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to CreateSipAccount page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.CreateSipAccount)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
createSIPAccountPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
spyBackButtonVisible.target = undefined
}
}
TestCase {
name: "Create Sip account ui flow"
when: windowShown
SignalSpy {
id: spyAccountIsReady
function test_createSipAccountUiFlow() {
uut.clearSignalSpy()
target: WizardViewStepModel
signalName: "accountIsReady"
}
var controlPanelStackView = findChild(uut, "controlPanelStackView")
SignalSpy {
id: spyAccountIsRemoved
var welcomePage = findChild(uut, "welcomePage")
var createSIPAccountPage = findChild(uut, "createSIPAccountPage")
target: AccountAdapter
signalName: "accountRemoved"
}
var sipUsernameEdit = findChild(createSIPAccountPage, "sipUsernameEdit")
var sipPasswordEdit = findChild(createSIPAccountPage, "sipPasswordEdit")
var sipServernameEdit = findChild(createSIPAccountPage, "sipServernameEdit")
var createAccountButton = findChild(createSIPAccountPage, "createSIPAccountButton")
SignalSpy {
id: spyAccountStatusChanged
// Go to createSipAccount page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.CreateSipAccount)
target: AccountAdapter
signalName: "accountStatusChanged"
}
// Set up paras
var userName = "testUserName"
var serverName = "testServerName"
var password = "testPassword"
var proxy = "testProxy"
SignalSpy {
id: spyAccountConfigFinalized
sipUsernameEdit.dynamicText = userName
sipPasswordEdit.dynamicText = password
sipServernameEdit.dynamicText = serverName
target: AccountAdapter
signalName: "accountConfigFinalized"
}
createAccountButton.clicked()
SignalSpy {
id: spyReportFailure
// Wait until the account creation is finished
spyAccountIsReady.wait()
compare(spyAccountIsReady.count, 1)
target: AccountAdapter
signalName: "reportFailure"
}
// Check if paras match with setup
compare(CurrentAccount.username, userName)
compare(CurrentAccount.hostname, serverName)
compare(CurrentAccount.password, password)
SignalSpy {
id: spyCloseWizardView
WizardViewStepModel.nextStep()
target: WizardViewStepModel
signalName: "closeWizardView"
}
spyCloseWizardView.wait()
compare(spyCloseWizardView.count, 1)
SignalSpy {
id: spyBackButtonVisible
AccountAdapter.deleteCurrentAccount()
signalName: "visibleChanged"
}
// Wait until the account removal is finished
spyAccountIsRemoved.wait()
compare(spyAccountIsRemoved.count, 1)
TestCase {
name: "WelcomePage to different account creation page and return back"
when: windowShown
function test_welcomePageStepInStepOut() {
var controlPanelStackView = findChild(uut, "controlPanelStackView")
var welcomePage = findChild(uut, "welcomePage")
var createAccountPage = findChild(uut, "createAccountPage")
var importFromDevicePage = findChild(uut, "importFromDevicePage")
var importFromBackupPage = findChild(uut, "importFromBackupPage")
var connectToAccountManagerPage = findChild(uut, "connectToAccountManagerPage")
var createSIPAccountPage = findChild(uut, "createSIPAccountPage")
// Go to createAccount page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.CreateJamiAccount)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
createAccountPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to CreateRendezVous page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.CreateRendezVous)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
createAccountPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to CreateRendezVous page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.ImportFromDevice)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
importFromDevicePage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to ImportFromBackup page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.ImportFromBackup)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
importFromBackupPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to ConnectToAccountManager page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.ConnectToAccountManager)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
connectToAccountManagerPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
// Go to CreateSipAccount page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.CreateSipAccount)
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
createSIPAccountPage)
WizardViewStepModel.previousStep()
compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
welcomePage)
}
}
TestCase {
name: "Create Sip account ui flow"
when: windowShown
function test_createSipAccountUiFlow() {
uut.clearSignalSpy()
var controlPanelStackView = findChild(uut, "controlPanelStackView")
var welcomePage = findChild(uut, "welcomePage")
var createSIPAccountPage = findChild(uut, "createSIPAccountPage")
var sipUsernameEdit = findChild(createSIPAccountPage, "sipUsernameEdit")
var sipPasswordEdit = findChild(createSIPAccountPage, "sipPasswordEdit")
var sipServernameEdit = findChild(createSIPAccountPage, "sipServernameEdit")
var createAccountButton = findChild(createSIPAccountPage, "createSIPAccountButton")
// Go to createSipAccount page
WizardViewStepModel.startAccountCreationFlow(
WizardViewStepModel.AccountCreationOption.CreateSipAccount)
// Set up paras
var userName = "testUserName"
var serverName = "testServerName"
var password = "testPassword"
var proxy = "testProxy"
sipUsernameEdit.dynamicText = userName
sipPasswordEdit.dynamicText = password
sipServernameEdit.dynamicText = serverName
createAccountButton.clicked()
// Wait until the account creation is finished
spyAccountIsReady.wait()
compare(spyAccountIsReady.count, 1)
// Check if paras match with setup
compare(CurrentAccount.username, userName)
compare(CurrentAccount.hostname, serverName)
compare(CurrentAccount.password, password)
WizardViewStepModel.nextStep()
spyCloseWizardView.wait()
compare(spyCloseWizardView.count, 1)
AccountAdapter.deleteCurrentAccount()
// Wait until the account removal is finished
spyAccountIsRemoved.wait()
compare(spyAccountIsRemoved.count, 1)
}
}
}
}

View File

@ -49,7 +49,7 @@ TEST_F(MessageParserFixture, TextIsParsedCorrectly)
// Wait for the messageParsed signal which should be emitted once.
messageParsedSpy.wait();
EXPECT_EQ(messageParsedSpy.count(), 1);
ASSERT_EQ(messageParsedSpy.count(), 1);
QList<QVariant> messageParserArguments = messageParsedSpy.takeFirst();
EXPECT_TRUE(messageParserArguments.at(0).typeId() == qMetaTypeId<QString>());
@ -60,7 +60,7 @@ TEST_F(MessageParserFixture, TextIsParsedCorrectly)
// No link info should be returned.
linkInfoReadySpy.wait();
EXPECT_EQ(linkInfoReadySpy.count(), 0);
ASSERT_EQ(linkInfoReadySpy.count(), 0);
}
/*!
@ -84,7 +84,7 @@ TEST_F(MessageParserFixture, ALinkIsParsedCorrectly)
// Wait for the messageParsed signal which should be emitted once.
messageParsedSpy.wait();
EXPECT_EQ(messageParsedSpy.count(), 1);
ASSERT_EQ(messageParsedSpy.count(), 1);
QList<QVariant> messageParserArguments = messageParsedSpy.takeFirst();
EXPECT_TRUE(messageParserArguments.at(0).typeId() == qMetaTypeId<QString>());
@ -96,7 +96,7 @@ TEST_F(MessageParserFixture, ALinkIsParsedCorrectly)
// Wait for the linkInfoReady signal which should be emitted once.
linkInfoReadySpy.wait();
EXPECT_EQ(linkInfoReadySpy.count(), 1);
ASSERT_EQ(linkInfoReadySpy.count(), 1);
QList<QVariant> linkInfoReadyArguments = linkInfoReadySpy.takeFirst();
EXPECT_TRUE(linkInfoReadyArguments.at(0).typeId() == qMetaTypeId<QString>());
@ -180,7 +180,7 @@ TEST_F(MessageParserFixture, EndOfLineCharactersAreParsedCorrectly)
// Wait for the messageParsed signal which should be emitted once.
messageParsedSpy.wait();
EXPECT_EQ(messageParsedSpy.count(), 1);
ASSERT_EQ(messageParsedSpy.count(), 1);
QList<QVariant> messageParserArguments = messageParsedSpy.takeFirst();
EXPECT_TRUE(messageParserArguments.at(0).typeId() == qMetaTypeId<QString>());
@ -210,7 +210,7 @@ TEST_F(MessageParserFixture, FencedCodeIsParsedCorrectly)
// Wait for the messageParsed signal which should be emitted once.
messageParsedSpy.wait();
EXPECT_EQ(messageParsedSpy.count(), 1);
ASSERT_EQ(messageParsedSpy.count(), 1);
QList<QVariant> messageParserArguments = messageParsedSpy.takeFirst();
EXPECT_TRUE(messageParserArguments.at(0).typeId() == qMetaTypeId<QString>());
@ -242,14 +242,14 @@ TEST_F(MessageParserFixture, YoutubeLinkIsParsedCorrectly)
// Wait for the messageParsed signal which should be emitted once.
messageParsedSpy.wait();
EXPECT_EQ(messageParsedSpy.count(), 1);
ASSERT_EQ(messageParsedSpy.count(), 1);
QList<QVariant> messageParserArguments = messageParsedSpy.takeFirst();
EXPECT_TRUE(messageParserArguments.at(0).typeId() == qMetaTypeId<QString>());
// Wait for the linkInfoReady signal which should be emitted once.
linkInfoReadySpy.wait();
EXPECT_EQ(linkInfoReadySpy.count(), 1);
ASSERT_EQ(linkInfoReadySpy.count(), 1);
QList<QVariant> linkInfoReadyArguments = linkInfoReadySpy.takeFirst();
EXPECT_TRUE(linkInfoReadyArguments.at(0).typeId() == qMetaTypeId<QString>());