/** * @copyright Copyright (c) Open-Xchange GmbH, Germany <info@open-xchange.com> * @license AGPL-3.0 * * This code is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with OX App Suite. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>. * * Any use of the work other than as authorized under this license or copyright law is prohibited. */ import { generateSimpleViteManifest, injectApp, mockConfig, mockFetch, mockRedis } from './util.js' import { expect } from 'chai' import * as td from 'testdouble' import RedisMock from 'ioredis-mock' import promClient from 'prom-client' describe('version mismatches', function () { let app let pubClient let runUpdate beforeEach(async function () { await mockConfig({ baseUrls: ['http://ui-server/'] }) const { createClient } = await mockRedis() mockFetch({ 'http://ui-server': { '/manifest.json': generateSimpleViteManifest({ 'foo.js': { }, 'bar.js': { } }), '/foo.js': td.when(td.func()(td.matchers.anything(), td.matchers.anything())).thenReturn( new Response('foo1', { headers: { version: '1' } }), new Response('foo2', { headers: { version: '2' } }) ), '/bar.js': td.when(td.func()(td.matchers.anything(), td.matchers.anything())).thenReturn( new Response('bar', { headers: { version: '2' } }), new Response('bar', { headers: { version: '2' } }), new Response('bar', { headers: { version: '3' } }) ), '/whatever.js': () => new Response('whatever', { headers: { version: '3' } }), '/meta.json': td.when(td.func()(td.matchers.anything(), td.matchers.anything())).thenReturn( new Response(JSON.stringify({ }), { headers: { 'Content-Type': 'application/json', version: '1' } }), new Response(JSON.stringify({ }), { headers: { 'Content-Type': 'application/json', version: '2' } }) ) } }) pubClient = createClient('pubClient') for (const prop of Object.getOwnPropertyNames(promClient.register._metrics)) { delete promClient.register._metrics[prop] } const { updateVersionProcessor } = await import('../src/version.js') runUpdate = updateVersionProcessor runUpdate(pubClient) app = await injectApp() }) afterEach(async function () { await new RedisMock().flushdb() td.reset() }) it('detects version mismatches when files are fetched', async function () { // get foo.js with initial version errors, due to the version mismatch // no partially complete state should be active (version 1) let response = await app.inject({ url: '/foo.js' }) expect(response.statusCode).to.equal(404) await runUpdate(pubClient) // update the version (version 2) response = await app.inject({ url: '/foo.js' }) expect(response.statusCode).to.equal(200) expect(response.body).to.equal('foo2') expect(response.headers.version).to.equal('85102502') // get bar.js. This will cause the server to detect the version mismatch response = await app.inject({ url: '/bar.js' }) expect(response.statusCode).to.equal(200) expect(response.body).to.equal('bar') await runUpdate(pubClient) // version 3 not successful but still version 2 in cache await runUpdate(pubClient) // get foo.js again. Since the versions should coincide now, the client should receive the new file response = await app.inject({ url: '/foo.js' }) expect(response.statusCode).to.equal(200) expect(response.body).to.equal('foo2') expect(response.headers.version).to.equal('85102502') }) it('detects version mismatches in files not referenced in manifest.json when files are fetched', async function () { // get foo.js with initial version 1 let response = await app.inject({ url: '/foo.js' }) expect(response.statusCode).to.equal(404) // update the version to 2 await runUpdate(pubClient) // get whatever.js. This will cause the server to detect the version mismatch response = await app.inject({ url: '/whatever.js' }) expect(response.statusCode).to.equal(404) await runUpdate(pubClient) // version 3 not successful but still version 2 in cache await runUpdate(pubClient) // bar should still be version 2 response = await app.inject({ url: '/bar.js' }) expect(response.statusCode).to.equal(200) expect(response.body).to.equal('bar') expect(response.headers.version).to.equal('85102502') }) })