First test if server is reachable and via https
Change-Id: I02bdb64e0300d2d7913e3929505eb2e5e29f79ea
diff --git a/test/korap-ui.js b/test/korap-ui.js
index f81193a..fcf1fcd 100644
--- a/test/korap-ui.js
+++ b/test/korap-ui.js
@@ -1,3 +1,4 @@
+const https = require('https');
const puppeteer = require('puppeteer-extra');
puppeteer.use(require('puppeteer-extra-plugin-user-preferences')({
userPrefs: {
@@ -32,6 +33,10 @@
describe('Running KorAP UI end-to-end tests on ' + KORAP_URL, () => {
+ let browser;
+ let page;
+
+
before(async () => {
browser = await puppeteer.launch({
headless: "shell",
@@ -51,21 +56,19 @@
height: 768,
deviceScaleFactor: 1,
});
- console.log("Browser version: " + await browser.version() + " started")
+
})
- after(async () => {
- await browser.close()
+ after(async function() {
+ if (browser && typeof browser.close === 'function') {
+ await browser.close();
+ }
})
afterEach(async function () {
if (this.currentTest.state == "failed") {
- const screenshotPath = "failed_" + this.currentTest.title.replaceAll(/[ &\/]/g, "_") + '.png';
- await page.screenshot({ path: screenshotPath });
-
if (slack) {
try {
- // First send text notification via webhook
slack.alert({
text: `🚨 Test on ${KORAP_URL} failed: *${this.currentTest.title}*`,
attachments: [{
@@ -86,87 +89,196 @@
}
}
- // Try to upload screenshot via Slack Web API if token is available
- const slackToken = process.env.SLACK_TOKEN;
- if (slackToken) {
- try {
- const { WebClient } = require('@slack/web-api');
- const fs = require('fs'); const web = new WebClient(slackToken);
- const channelId = process.env.SLACK_CHANNEL_ID || 'C07CM4JS48H';
+ // Only take screenshot if it's not one of the initial connectivity/SSL tests
+ const initialTestTitles = [
+ 'should be reachable',
+ 'should have a valid SSL certificate'
+ ];
+ if (!initialTestTitles.includes(this.currentTest.title) && page) {
+ const screenshotPath = "failed_" + this.currentTest.title.replaceAll(/[ &\/]/g, "_") + '.png';
+ await page.screenshot({ path: screenshotPath });
- // Upload the file to Slack
- const result = await web.files.uploadV2({
- channel_id: channelId,
- file: fs.createReadStream(screenshotPath),
- filename: screenshotPath,
- title: `Screenshot: ${this.currentTest.title}`,
- initial_comment: `📸 Screenshot of failed test: ${this.currentTest.title} on ${KORAP_URL}`
- });
+ const slackToken = process.env.SLACK_TOKEN;
+ if (slackToken) {
+ try {
+ const { WebClient } = require('@slack/web-api');
+ const fs = require('fs'); const web = new WebClient(slackToken);
+ const channelId = process.env.SLACK_CHANNEL_ID || 'C07CM4JS48H';
- console.log('Screenshot uploaded to Slack successfully');
+ const result = await web.files.uploadV2({
+ channel_id: channelId,
+ file: fs.createReadStream(screenshotPath),
+ filename: screenshotPath,
+ title: `Screenshot: ${this.currentTest.title}`,
+ initial_comment: `📸 Screenshot of failed test: ${this.currentTest.title} on ${KORAP_URL}`
+ });
- } catch (uploadError) {
- console.error('Failed to upload screenshot to Slack:', uploadError.message);
+ } catch (uploadError) {
+ console.error('Failed to upload screenshot to Slack:', uploadError.message);
+ }
}
}
}
})
- it('KorAP UI is up and running',
- (async () => {
- page.goto(KORAP_URL);
- await page.waitForNavigation({ waitUntil: 'networkidle2' });
- const query_field = await page.$("#q-field")
- assert.isNotNull(query_field, "#q-field not found. Kalamar not running?");
- }))
+ it('should be reachable', function (done) {
+ let doneCalled = false;
+ const url = new URL(KORAP_URL);
+ const httpModule = url.protocol === 'https:' ? https : require('http');
+ const req = httpModule.request({
+ method: 'HEAD',
+ hostname: url.hostname,
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
+ path: url.pathname,
+ timeout: 5000
+ }, res => {
+ if (!doneCalled) {
+ doneCalled = true;
+ if (res.statusCode >= 200 && res.statusCode < 400) {
+ done();
+ } else {
+ done(new Error(`Server is not reachable. Status code: ${res.statusCode}`));
+ }
+ }
+ });
+ req.on('timeout', () => {
+ if (!doneCalled) {
+ doneCalled = true;
+ req.destroy();
+ done(new Error('Request to server timed out.'));
+ }
+ });
+ req.on('error', err => {
+ if (!doneCalled) {
+ doneCalled = true;
+ done(err);
+ }
+ });
+ req.end();
+ });
- ifConditionIt('Login into KorAP with incorrect credentials fails',
- KORAP_LOGIN != "",
- (async () => {
- const login_result = await korap_rc.login(page, KORAP_LOGIN, KORAP_PWD + "*")
- login_result.should.be.false
- }))
+ it('should have a valid SSL certificate', function (done) {
+ let doneCalled = false;
+ const url = new URL(KORAP_URL);
+ if (url.protocol !== 'https:') {
+ return this.skip();
+ }
+ const req = https.request({
+ method: 'HEAD',
+ hostname: url.hostname,
+ port: url.port || 443,
+ path: url.pathname,
+ timeout: 5000
+ }, res => {
+ if (!doneCalled) {
+ doneCalled = true;
+ const cert = res.socket.getPeerCertificate();
+ if (cert && cert.valid_to) {
+ const validTo = new Date(cert.valid_to);
+ if (validTo > new Date()) {
+ done();
+ } else {
+ done(new Error(`SSL certificate expired on ${validTo.toDateString()}`));
+ }
+ } else if (res.socket.isSessionReused()){
+ done();
+ }
+ else {
+ done(new Error('Could not retrieve SSL certificate information.'));
+ }
+ }
+ });
+ req.on('timeout', () => {
+ if (!doneCalled) {
+ doneCalled = true;
+ req.destroy();
+ done(new Error('Request to server timed out.'));
+ }
+ });
+ req.on('error', err => {
+ if (!doneCalled) {
+ doneCalled = true;
+ if (err.code === 'CERT_HAS_EXPIRED') {
+ done(new Error('SSL certificate has expired.'));
+ } else {
+ done(err);
+ }
+ }
+ });
+ req.end();
+ });
- ifConditionIt('Login into KorAP with correct credentials succeeds',
- KORAP_LOGIN != "",
- (async () => {
- const login_result = await korap_rc.login(page, KORAP_LOGIN, KORAP_PWD)
- login_result.should.be.true
- }))
+ describe('UI Tests', function() {
- it('Can turn glimpse off',
- (async () => {
- await korap_rc.assure_glimpse_off(page)
- }))
+ before(function() {
+ // Check the state of the parent suite's tests
+ const initialTests = this.test.parent.parent.tests;
+ if (initialTests[0].state === 'failed' || initialTests[1].state === 'failed') {
+ this.skip();
+ }
+ });
- it('Corpus statistics show sufficient tokens',
- (async () => {
- const tokenCount = await korap_rc.check_corpus_statistics(page, KORAP_MIN_TOKENS_IN_CORPUS);
- console.log(`Found ${tokenCount} tokens in corpus, minimum required: ${KORAP_MIN_TOKENS_IN_CORPUS}`);
- tokenCount.should.be.above(KORAP_MIN_TOKENS_IN_CORPUS - 1,
- `Corpus should have at least ${KORAP_MIN_TOKENS_IN_CORPUS} tokens, but found ${tokenCount}`);
- })).timeout(50000)
+
- describe('Running searches that should have hits', () => {
-
- before(async () => { await korap_rc.login(page, KORAP_LOGIN, KORAP_PWD) })
-
- KORAP_QUERIES.split(/[;,] */).forEach((query, i) => {
- it('Search for "' + query + '" has hits',
- (async () => {
- await korap_rc.assure_glimpse_off(page)
- const hits = await korap_rc.search(page, query)
- hits.should.be.above(0)
- })).timeout(20000)
+ it('KorAP UI is up and running', async function () {
+ try {
+ await page.goto(KORAP_URL, { waitUntil: 'domcontentloaded' });
+ await page.waitForSelector("#q-field", { visible: true });
+ const query_field = await page.$("#q-field")
+ assert.isNotNull(query_field, "#q-field not found. Kalamar not running?");
+ } catch (error) {
+ throw new Error(`Failed to load KorAP UI or find query field: ${error.message}`);
+ }
})
- })
- ifConditionIt('Logout works',
- KORAP_LOGIN != "",
- (async () => {
- const logout_result = await korap_rc.logout(page)
- logout_result.should.be.true
- })).timeout(15000)
-})
+ ifConditionIt('Login into KorAP with incorrect credentials fails',
+ KORAP_LOGIN != "",
+ (async () => {
+ const login_result = await korap_rc.login(page, KORAP_LOGIN, KORAP_PWD + "*")
+ login_result.should.be.false
+ }))
+
+ ifConditionIt('Login into KorAP with correct credentials succeeds',
+ KORAP_LOGIN != "",
+ (async () => {
+ const login_result = await korap_rc.login(page, KORAP_LOGIN, KORAP_PWD)
+ login_result.should.be.true
+ }))
+
+ it('Can turn glimpse off',
+ (async () => {
+ await korap_rc.assure_glimpse_off(page)
+ }))
+
+ it('Corpus statistics show sufficient tokens',
+ (async () => {
+ const tokenCount = await korap_rc.check_corpus_statistics(page, KORAP_MIN_TOKENS_IN_CORPUS);
+ console.log(`Found ${tokenCount} tokens in corpus, minimum required: ${KORAP_MIN_TOKENS_IN_CORPUS}`);
+ tokenCount.should.be.above(KORAP_MIN_TOKENS_IN_CORPUS - 1,
+ `Corpus should have at least ${KORAP_MIN_TOKENS_IN_CORPUS} tokens, but found ${tokenCount}`);
+ })).timeout(90000)
+
+ describe('Running searches that should have hits', () => {
+
+ before(async () => { await korap_rc.login(page, KORAP_LOGIN, KORAP_PWD) })
+
+ KORAP_QUERIES.split(/[;,] */).forEach((query, i) => {
+ it('Search for "' + query + '" has hits',
+ (async () => {
+ await korap_rc.assure_glimpse_off(page)
+ const hits = await korap_rc.search(page, query)
+ hits.should.be.above(0)
+ })).timeout(20000)
+ })
+ })
+
+ ifConditionIt('Logout works',
+ KORAP_LOGIN != "",
+ (async () => {
+ const logout_result = await korap_rc.logout(page)
+ logout_result.should.be.true
+ })).timeout(15000)
+ });
+});
\ No newline at end of file