summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/printing/tst_printing.cpp
blob: 605fb57b5c7645dd39fe70e65066958c298beffa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
#include <QtWebEngineCore/qtwebenginecore-config.h>
#include <QWebEngineSettings>
#include <QWebEngineView>
#include <QTemporaryDir>
#include <QTest>
#include <QSignalSpy>
#include <util.h>

#if QT_CONFIG(webengine_system_poppler)
#include <poppler-document.h>
#include <poppler-page.h>
#endif

class tst_Printing : public QObject
{
    Q_OBJECT
private slots:
    void printToPdfBasic();
    void printRequest();
#if QT_CONFIG(webengine_system_poppler)
    void printToPdfPoppler();
    void printFromPdfViewer();
#endif
    void interruptPrinting();
};

void tst_Printing::printToPdfBasic()
{
    QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX");
    QVERIFY(tempDir.isValid());
    QWebEngineView view;
    QSignalSpy spy(&view, &QWebEngineView::loadFinished);
    view.load(QUrl("qrc:///resources/basic_printing_page.html"));
    QTRY_VERIFY(spy.size() == 1);

    QSignalSpy savePdfSpy(view.page(), &QWebEnginePage::pdfPrintingFinished);
    QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0));
    QString path = tempDir.path() + "/print_1_success.pdf";
    view.page()->printToPdf(path, layout);
    QTRY_VERIFY2(savePdfSpy.size() == 1, "Printing to PDF file failed without signal");

    QList<QVariant> successArguments = savePdfSpy.takeFirst();
    QVERIFY2(successArguments.at(0).toString() == path, "File path for first saved PDF does not match arguments");
    QVERIFY2(successArguments.at(1).toBool() == true, "Printing to PDF file failed though it should succeed");

#if !defined(Q_OS_WIN)
    path = tempDir.path() + "/print_//2_failed.pdf";
#else
    path = tempDir.path() + "/print_|2_failed.pdf";
#endif
    view.page()->printToPdf(path, QPageLayout());
    QTRY_VERIFY2(savePdfSpy.size() == 1, "Printing to PDF file failed without signal");

    QList<QVariant> failedArguments = savePdfSpy.takeFirst();
    QVERIFY2(failedArguments.at(0).toString() == path, "File path for second saved PDF does not match arguments");
    QVERIFY2(failedArguments.at(1).toBool() == false, "Printing to PDF file succeeded though it should fail");

    CallbackSpy<QByteArray> successfulSpy;
    view.page()->printToPdf(successfulSpy.ref(), layout);
    QVERIFY(successfulSpy.waitForResult().size() > 0);

    CallbackSpy<QByteArray> failedInvalidLayoutSpy;
    view.page()->printToPdf(failedInvalidLayoutSpy.ref(), QPageLayout());
    QCOMPARE(failedInvalidLayoutSpy.waitForResult().size(), 0);
}

void tst_Printing::printRequest()
{
     QWebEngineView view;
     QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0));
     QSignalSpy loadFinishedSpy(&view, &QWebEngineView::loadFinished);
     QSignalSpy printRequestedSpy(&view, &QWebEngineView::printRequested);
     QSignalSpy printRequestedSpy2(view.page(), &QWebEnginePage::printRequested);
     QSignalSpy savePdfSpy(&view, &QWebEngineView::pdfPrintingFinished);
     CallbackSpy<QByteArray> resultSpy;

     view.load(QUrl("qrc:///resources/basic_printing_page.html"));
     QTRY_VERIFY(loadFinishedSpy.size() == 1);
     view.page()->runJavaScript("window.print()");
     QTRY_VERIFY(printRequestedSpy.size() == 1);
     QVERIFY(printRequestedSpy2.size() == 1);
     //check if printing still works
     view.printToPdf(resultSpy.ref(), layout);
     const QByteArray data = resultSpy.waitForResult();
     QVERIFY(data.size() > 0);
}

#if QT_CONFIG(webengine_system_poppler)
void tst_Printing::printToPdfPoppler()
{
    // check if generated pdf is correct by searching for a know string on the page
    using namespace poppler;
    QWebEngineView view;
    QPageLayout layout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0));

    QSignalSpy spy(&view, &QWebEngineView::loadFinished);
    QSignalSpy savePdfSpy(&view, &QWebEngineView::pdfPrintingFinished);
    CallbackSpy<QByteArray> resultSpy;

    view.load(QUrl("qrc:///resources/basic_printing_page.html"));
    QTRY_VERIFY(spy.count() == 1);
    view.printToPdf(resultSpy.ref(), layout);
    const QByteArray data = resultSpy.waitForResult();
    QVERIFY(data.length() > 0);

    QScopedPointer<document> pdf(document::load_from_raw_data(data.constData(), data.length()));
    QVERIFY(pdf);

    const int pages = pdf->pages();
    QVERIFY(pages == 1);

    QScopedPointer<page> pdfPage(pdf->create_page(0));
    rectf rect;
    QVERIFY2(pdfPage->search(ustring::from_latin1("Hello Paper World"), rect, page::search_from_top,
                     case_sensitive ), "Could not find text");
}

void tst_Printing::printFromPdfViewer()
{
    using namespace poppler;

    QWebEngineView view;
    view.page()->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
    view.page()->settings()->setAttribute(QWebEngineSettings::PdfViewerEnabled, true);

    // Load a basic HTML
    QSignalSpy spy(&view, &QWebEngineView::loadFinished);
    view.load(QUrl("qrc:///resources/basic_printing_page.html"));
    QTRY_COMPARE(spy.size(), 1);

    // Create a PDF
    QTemporaryDir tempDir(QDir::tempPath() + "/tst_printing-XXXXXX");
    QVERIFY(tempDir.isValid());
    QString path = tempDir.path() + "/basic_page.pdf";
    QSignalSpy savePdfSpy(view.page(), &QWebEnginePage::pdfPrintingFinished);
    view.page()->printToPdf(path);
    QTRY_COMPARE(savePdfSpy.size(), 1);

    // Open the new file with the PDF viewer plugin
    view.load(QUrl("file://" + path));
    QTRY_COMPARE(spy.size(), 2);

    // Print from the plugin
    // loadFinished signal is not reliable when loading a PDF file, because it has multiple phases.
    // Workaround: Try to print it a couple of times until the result matches the expected.
    CallbackSpy<QByteArray> resultSpy;
    bool ok = QTest::qWaitFor([&]() -> bool {
        view.printToPdf(resultSpy.ref());
        QByteArray data = resultSpy.waitForResult();

        // Check if the result contains text from the original basic HTML
        // This catches all the typical issues: empty result or printing the WebUI without PDF content.
        QScopedPointer<document> pdf(document::load_from_raw_data(data.constData(), data.length()));
        QScopedPointer<page> pdfPage(pdf->create_page(0));
        rectf rect;
        return pdfPage->search(ustring::from_latin1("Hello Paper World"), rect, page::search_from_top,
                            case_sensitive);
    }, 10000);
    QVERIFY(ok);
}
#endif

void tst_Printing::interruptPrinting()
{
    QWebEngineView view;
    QSignalSpy spy(&view, &QWebEngineView::loadFinished);
    view.load(QUrl("qrc:///resources/basic_printing_page.html"));
    QTRY_VERIFY(spy.size() == 1);

    QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX");
    QVERIFY(tempDir.isValid());
    view.page()->printToPdf(tempDir.path() + "/file.pdf");
    // Navigation stop interrupts print job, preferably do this without crash/assert
    view.page()->triggerAction(QWebEnginePage::Stop);
}

QTEST_MAIN(tst_Printing)
#include "tst_printing.moc"