From 3d97d71b347eaae14bb3c5130af4294eb1892394 Mon Sep 17 00:00:00 2001 From: fflorent Date: Tue, 14 May 2024 14:47:58 +0200 Subject: [PATCH 1/5] Achieved to make test that test doc worker work --- test/server/lib/DocApi.ts | 13 +++++++++---- test/server/lib/helpers/TestServer.ts | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/test/server/lib/DocApi.ts b/test/server/lib/DocApi.ts index 3d9b1f854a..2db1fc9607 100644 --- a/test/server/lib/DocApi.ts +++ b/test/server/lib/DocApi.ts @@ -172,8 +172,10 @@ describe('DocApi', function () { ...overrideEnvConf }; const home = await TestServer.startServer('home', tmpDir, suitename, additionalEnvConfiguration); - const docs = await TestServer.startServer( - 'docs', tmpDir, suitename, additionalEnvConfiguration, home.serverUrl + const docs = await TestServer.startServer('docs', tmpDir, suitename, { + ...additionalEnvConfiguration, + APP_DOC_URL: `${await proxy.getServerUrl()}/dw/dw1`, + }, home.serverUrl ); proxy.requireFromOutsideHeader(); @@ -2915,7 +2917,7 @@ function testDocApi() { }); it('POST /workspaces/{wid}/import handles empty filenames', async function () { - if (!process.env.TEST_REDIS_URL || docs.proxiedServer) { + if (!process.env.TEST_REDIS_URL) { this.skip(); } const worker1 = await userApi.getWorkerAPI('import'); @@ -5356,7 +5358,10 @@ function setup(name: string, cb: () => Promise) { await cb(); // create TestDoc as an empty doc into Private workspace - userApi = api = home.makeUserApi(ORG_NAME); + userApi = api = home.makeUserApi(ORG_NAME, 'chimpy', { + headers: makeConfig('chimpy').headers as Record, + serverUrl + }); const wid = await getWorkspaceId(api, 'Private'); docIds.TestDoc = await api.newDoc({name: 'TestDoc'}, wid); }); diff --git a/test/server/lib/helpers/TestServer.ts b/test/server/lib/helpers/TestServer.ts index 959468598f..0ba24a2d83 100644 --- a/test/server/lib/helpers/TestServer.ts +++ b/test/server/lib/helpers/TestServer.ts @@ -88,6 +88,9 @@ export class TestServer { APP_HOME_INTERNAL_URL: homeUrl, GRIST_TESTING_SOCKET: this.testingSocket, GRIST_PORT: String(port), + ...(this._serverTypes.includes('docs') ? { + APP_DOC_INTERNAL_URL: this._serverUrl, + }: {}), ...this._defaultEnv, ...customEnv }; @@ -258,7 +261,7 @@ export class TestServerReverseProxy { } public async start(homeServer: TestServer, docServer: TestServer) { - this._app.all(['/dw/dw1', '/dw/dw1/*'], (oreq, ores) => this._getRequestHandlerFor(docServer)); + this._app.all(['/dw/dw1', '/dw/dw1/*'], this._getRequestHandlerFor(docServer)); this._app.all('/*', this._getRequestHandlerFor(homeServer)); // Forbid now the use of serverUrl property, so we don't allow the tests to From 7b913825802af19ad571b836604a72639975a96d Mon Sep 17 00:00:00 2001 From: fflorent Date: Tue, 14 May 2024 15:22:12 +0200 Subject: [PATCH 2/5] TestServer: Make _serverUrl a Promise --- test/server/lib/DocApi.ts | 35 ++++++++++---------- test/server/lib/ManyFetches.ts | 8 ++--- test/server/lib/UnhandledErrors.ts | 4 +-- test/server/lib/Webhooks-Proxy.ts | 14 ++++---- test/server/lib/helpers/TestServer.ts | 47 +++++++++++++++------------ 5 files changed, 58 insertions(+), 50 deletions(-) diff --git a/test/server/lib/DocApi.ts b/test/server/lib/DocApi.ts index 2db1fc9607..c27e94d753 100644 --- a/test/server/lib/DocApi.ts +++ b/test/server/lib/DocApi.ts @@ -118,7 +118,7 @@ describe('DocApi', function () { GRIST_DATA_DIR: dataDir }; home = docs = await TestServer.startServer('home,docs', tmpDir, suitename, additionalEnvConfiguration); - homeUrl = serverUrl = home.serverUrl; + homeUrl = serverUrl = await home.getServerUrl(); hasHomeApi = true; }); testDocApi(); @@ -132,7 +132,7 @@ describe('DocApi', function () { GRIST_ANON_PLAYGROUND: 'false' }; home = docs = await TestServer.startServer('home,docs', tmpDir, suitename, additionalEnvConfiguration); - homeUrl = serverUrl = home.serverUrl; + homeUrl = serverUrl = await home.getServerUrl(); hasHomeApi = true; }); @@ -153,8 +153,8 @@ describe('DocApi', function () { }; home = await TestServer.startServer('home', tmpDir, suitename, additionalEnvConfiguration); - docs = await TestServer.startServer('docs', tmpDir, suitename, additionalEnvConfiguration, home.serverUrl); - homeUrl = serverUrl = home.serverUrl; + homeUrl = serverUrl = await home.getServerUrl(); + docs = await TestServer.startServer('docs', tmpDir, suitename, additionalEnvConfiguration, homeUrl); hasHomeApi = true; }); testDocApi(); @@ -175,8 +175,7 @@ describe('DocApi', function () { const docs = await TestServer.startServer('docs', tmpDir, suitename, { ...additionalEnvConfiguration, APP_DOC_URL: `${await proxy.getServerUrl()}/dw/dw1`, - }, home.serverUrl - ); + }, await home.getServerUrl()); proxy.requireFromOutsideHeader(); await proxy.start(home, docs); @@ -214,7 +213,7 @@ describe('DocApi', function () { async function testCompareDocs(proxy: TestServerReverseProxy, home: TestServer) { const chimpy = makeConfig('chimpy'); const userApiServerUrl = await proxy.getServerUrl(); - const chimpyApi = home.makeUserApi( + const chimpyApi = await home.makeUserApi( ORG_NAME, 'chimpy', { serverUrl: userApiServerUrl, headers: chimpy.headers as Record } ); const ws1 = (await chimpyApi.getOrgWorkspaces('current'))[0].id; @@ -258,9 +257,9 @@ describe('DocApi', function () { GRIST_DATA_DIR: dataDir }; home = await TestServer.startServer('home', tmpDir, suitename, additionalEnvConfiguration); - docs = await TestServer.startServer('docs', tmpDir, suitename, additionalEnvConfiguration, home.serverUrl); - homeUrl = home.serverUrl; - serverUrl = docs.serverUrl; + homeUrl = await home.getServerUrl(); + docs = await TestServer.startServer('docs', tmpDir, suitename, additionalEnvConfiguration, homeUrl); + serverUrl = await docs.getServerUrl(); hasHomeApi = false; }); testDocApi(); @@ -350,7 +349,7 @@ function testDocApi() { const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; // Make sure kiwi isn't allowed here. await userApi.updateOrgPermissions(ORG_NAME, {users: {[kiwiEmail]: null}}); - const kiwiApi = home.makeUserApi(ORG_NAME, 'kiwi'); + const kiwiApi = await home.makeUserApi(ORG_NAME, 'kiwi'); await assert.isRejected(kiwiApi.getWorkspaceAccess(ws1), /Forbidden/); // Add kiwi as an editor for the org. await assert.isRejected(kiwiApi.getOrgAccess(ORG_NAME), /Forbidden/); @@ -370,7 +369,7 @@ function testDocApi() { const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; await userApi.updateOrgPermissions(ORG_NAME, {users: {[kiwiEmail]: null}}); // Make sure kiwi isn't allowed here. - const kiwiApi = home.makeUserApi(ORG_NAME, 'kiwi'); + const kiwiApi = await home.makeUserApi(ORG_NAME, 'kiwi'); await assert.isRejected(kiwiApi.getWorkspaceAccess(ws1), /Forbidden/); // Add kiwi as an editor of this workspace. await userApi.updateWorkspacePermissions(ws1, {users: {[kiwiEmail]: 'editors'}}); @@ -389,7 +388,7 @@ function testDocApi() { it("should allow only owners to remove a document", async () => { const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; const doc1 = await userApi.newDoc({name: 'testdeleteme1'}, ws1); - const kiwiApi = home.makeUserApi(ORG_NAME, 'kiwi'); + const kiwiApi = await home.makeUserApi(ORG_NAME, 'kiwi'); // Kiwi is editor of the document, so he can't delete it. await userApi.updateDocPermissions(doc1, {users: {'kiwi@getgrist.com': 'editors'}}); @@ -405,7 +404,7 @@ function testDocApi() { it("should allow only owners to rename a document", async () => { const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; const doc1 = await userApi.newDoc({name: 'testrenameme1'}, ws1); - const kiwiApi = home.makeUserApi(ORG_NAME, 'kiwi'); + const kiwiApi = await home.makeUserApi(ORG_NAME, 'kiwi'); // Kiwi is editor of the document, so he can't rename it. await userApi.updateDocPermissions(doc1, {users: {'kiwi@getgrist.com': 'editors'}}); @@ -3454,7 +3453,7 @@ function testDocApi() { if (docs.proxiedServer) { this.skip(); } - const docWorkerUrl = docs.serverUrl; + const docWorkerUrl = await docs.getServerUrl(); let resp = await axios.get(`${docWorkerUrl}/api/docs/${docIds.Timesheets}/tables/Table1/data`, chimpy); assert.equal(resp.status, 200); assert.containsAllKeys(resp.data, ['A', 'B', 'C']); @@ -3758,7 +3757,7 @@ function testDocApi() { it("limits daily API usage", async function () { // Make a new document in a test product with a low daily limit - const api = home.makeUserApi('testdailyapilimit'); + const api = await home.makeUserApi('testdailyapilimit'); const workspaceId = await getWorkspaceId(api, 'TestDailyApiLimitWs'); const docId = await api.newDoc({name: 'TestDoc1'}, workspaceId); const max = testDailyApiLimitFeatures.baseMaxApiUnitsPerDocumentPerDay; @@ -3786,7 +3785,7 @@ function testDocApi() { it("limits daily API usage and sets the correct keys in redis", async function () { this.retries(3); // Make a new document in a free team site, currently the only real product which limits daily API usage. - const freeTeamApi = home.makeUserApi('freeteam'); + const freeTeamApi = await home.makeUserApi('freeteam'); const workspaceId = await getWorkspaceId(freeTeamApi, 'FreeTeamWs'); const docId = await freeTeamApi.newDoc({name: 'TestDoc2'}, workspaceId); // Rather than making 5000 requests, set high counts directly for the current and next daily and hourly keys @@ -5358,7 +5357,7 @@ function setup(name: string, cb: () => Promise) { await cb(); // create TestDoc as an empty doc into Private workspace - userApi = api = home.makeUserApi(ORG_NAME, 'chimpy', { + userApi = api = await home.makeUserApi(ORG_NAME, 'chimpy', { headers: makeConfig('chimpy').headers as Record, serverUrl }); diff --git a/test/server/lib/ManyFetches.ts b/test/server/lib/ManyFetches.ts index 59db25514a..788f94f1d0 100644 --- a/test/server/lib/ManyFetches.ts +++ b/test/server/lib/ManyFetches.ts @@ -48,8 +48,8 @@ describe('ManyFetches', function() { // Without this limit, there is no pressure on node to garbage-collect, so it may use more // memory than we expect, making the test less reliable. NODE_OPTIONS: '--max-old-space-size=210', - }, home.serverUrl); - userApi = home.makeUserApi(org, userName); + }, await home.getServerUrl()); + userApi = await home.makeUserApi(org, userName); }); afterEach(async function() { @@ -222,13 +222,13 @@ describe('ManyFetches', function() { // function. async function prepareGristWSConnection(docId: string): Promise<() => GristWSConnection> { // Use cookies for access to stay as close as possible to regular operation. - const resp = await fetch(`${home.serverUrl}/test/session`); + const resp = await fetch(`${await home.getServerUrl()}/test/session`); const sid = cookie.parse(resp.headers.get('set-cookie'))[cookieName]; if (!sid) { throw new Error('no session available'); } await home.testingHooks.setLoginSessionProfile(sid, {name: userName, email}, org); // Load the document html. - const pageUrl = `${home.serverUrl}/o/docs/doc/${docId}`; + const pageUrl = `${await home.getServerUrl()}/o/docs/doc/${docId}`; const headers = {Cookie: `${cookieName}=${sid}`}; const doc = await fetch(pageUrl, {headers}); const pageBody = await doc.text(); diff --git a/test/server/lib/UnhandledErrors.ts b/test/server/lib/UnhandledErrors.ts index 8aad3fcc55..d6da424a03 100644 --- a/test/server/lib/UnhandledErrors.ts +++ b/test/server/lib/UnhandledErrors.ts @@ -40,7 +40,7 @@ describe('UnhandledErrors', function() { const server = await TestServer.startServer('home', testDir, errType, undefined, undefined, {output}); try { - assert.equal((await fetch(`${server.serverUrl}/status`)).status, 200); + assert.equal((await fetch(`${await server.getServerUrl()}/status`)).status, 200); serverLogLines.length = 0; // Trigger an unhandled error, and check that the server logged it and attempted cleanup. @@ -51,7 +51,7 @@ describe('UnhandledErrors', function() { }, 1000, 100); // We expect the server to be dead now. - await assert.isRejected(fetch(`${server.serverUrl}/status`), /failed.*ECONNREFUSED/); + await assert.isRejected(fetch(`${await server.getServerUrl()}/status`), /failed.*ECONNREFUSED/); } finally { await server.stop(); diff --git a/test/server/lib/Webhooks-Proxy.ts b/test/server/lib/Webhooks-Proxy.ts index f929c66711..19c094d604 100644 --- a/test/server/lib/Webhooks-Proxy.ts +++ b/test/server/lib/Webhooks-Proxy.ts @@ -71,7 +71,7 @@ describe('Webhooks-Proxy', function () { await cb(); // create TestDoc as an empty doc into Private workspace - userApi = api = home.makeUserApi(ORG_NAME); + userApi = api = await home.makeUserApi(ORG_NAME); const wid = await getWorkspaceId(api, 'Private'); docIds.TestDoc = await api.newDoc({name: 'TestDoc'}, wid); }); @@ -125,7 +125,7 @@ describe('Webhooks-Proxy', function () { describe("should work with a merged server", async () => { setupMockServers('merged', tmpDir, async () => { home = docs = await TestServer.startServer('home,docs', tmpDir, suitename, additionaEnvConfiguration); - serverUrl = home.serverUrl; + serverUrl = await home.getServerUrl(); }); subTestCall(); }); @@ -135,8 +135,9 @@ describe('Webhooks-Proxy', function () { describe("should work with a home server and a docworker", async () => { setupMockServers('separated', tmpDir, async () => { home = await TestServer.startServer('home', tmpDir, suitename, additionaEnvConfiguration); - docs = await TestServer.startServer('docs', tmpDir, suitename, additionaEnvConfiguration, home.serverUrl); - serverUrl = home.serverUrl; + const homeUrl = await home.getServerUrl(); + docs = await TestServer.startServer('docs', tmpDir, suitename, additionaEnvConfiguration, homeUrl); + serverUrl = homeUrl; }); subTestCall(); }); @@ -145,8 +146,9 @@ describe('Webhooks-Proxy', function () { describe("should work directly with a docworker", async () => { setupMockServers('docs', tmpDir, async () => { home = await TestServer.startServer('home', tmpDir, suitename, additionaEnvConfiguration); - docs = await TestServer.startServer('docs', tmpDir, suitename, additionaEnvConfiguration, home.serverUrl); - serverUrl = docs.serverUrl; + const homeUrl = await home.getServerUrl(); + docs = await TestServer.startServer('docs', tmpDir, suitename, additionaEnvConfiguration, homeUrl); + serverUrl = await docs.getServerUrl(); }); subTestCall(); }); diff --git a/test/server/lib/helpers/TestServer.ts b/test/server/lib/helpers/TestServer.ts index 0ba24a2d83..151e38357a 100644 --- a/test/server/lib/helpers/TestServer.ts +++ b/test/server/lib/helpers/TestServer.ts @@ -37,15 +37,9 @@ export class TestServer { public testingSocket: string; public testingHooks: TestingHooksClient; public stopped = false; - public get serverUrl() { - if (this._proxiedServer) { - throw new Error('Direct access to this test server is disallowed'); - } - return this._serverUrl; - } public get proxiedServer() { return this._proxiedServer; } - private _serverUrl: string; + private _serverUrl: Promise; private _server: ChildProcess; private _exitPromise: Promise; private _proxiedServer: boolean = false; @@ -65,7 +59,20 @@ export class TestServer { GRIST_MAX_QUEUE_SIZE: '10', ...process.env }; + this._serverUrl = new Promise((resolve) => { + return getAvailablePort().then((port) => { + resolve(`http://localhost:${port}`); + }); + }); } + + public getServerUrl() { + if (this._proxiedServer) { + throw new Error('Direct access to this test server is disallowed'); + } + return this._serverUrl; + } + public async start(_homeUrl?: string, customEnv?: NodeJS.ProcessEnv, options: {output?: Writable} = {}) { // put node logs into files with meaningful name that relate to the suite name and server type const fixedName = this._serverTypes.replace(/,/, '_'); @@ -79,17 +86,17 @@ export class TestServer { throw new Error(`Path of testingSocket too long: ${this.testingSocket.length} (${this.testingSocket})`); } - const port = await getAvailablePort(); - this._serverUrl = `http://localhost:${port}`; - const homeUrl = _homeUrl ?? (this._serverTypes.includes('home') ? this._serverUrl : undefined); + const serverUrl = await this.getServerUrl(); + const port = new URL(serverUrl).port; + const homeUrl = _homeUrl ?? (this._serverTypes.includes('home') ? serverUrl : undefined); const env: NodeJS.ProcessEnv = { APP_HOME_URL: homeUrl, APP_HOME_INTERNAL_URL: homeUrl, GRIST_TESTING_SOCKET: this.testingSocket, - GRIST_PORT: String(port), + GRIST_PORT: port, ...(this._serverTypes.includes('docs') ? { - APP_DOC_INTERNAL_URL: this._serverUrl, + APP_DOC_INTERNAL_URL: serverUrl, }: {}), ...this._defaultEnv, ...customEnv @@ -160,18 +167,18 @@ export class TestServer { // Returns the promise for the ChildProcess's signal or exit code. public getExitPromise(): Promise { return this._exitPromise; } - public makeUserApi( + public async makeUserApi( org: string, user: string = 'chimpy', { headers = {Authorization: `Bearer api_key_for_${user}`}, - serverUrl = this._serverUrl, + serverUrl }: { headers?: Record serverUrl?: string, } = { headers: undefined, serverUrl: undefined }, - ): UserAPIImpl { - return new UserAPIImpl(`${serverUrl}/o/${org}`, { + ): Promise { + return new UserAPIImpl(`${serverUrl ?? await this.getServerUrl()}/o/${org}`, { headers, fetch: fetch as unknown as typeof globalThis.fetch, newFormData: () => new FormData() as any, @@ -261,8 +268,8 @@ export class TestServerReverseProxy { } public async start(homeServer: TestServer, docServer: TestServer) { - this._app.all(['/dw/dw1', '/dw/dw1/*'], this._getRequestHandlerFor(docServer)); - this._app.all('/*', this._getRequestHandlerFor(homeServer)); + this._app.all(['/dw/dw1', '/dw/dw1/*'], await this._getRequestHandlerFor(docServer)); + this._app.all('/*', await this._getRequestHandlerFor(homeServer)); // Forbid now the use of serverUrl property, so we don't allow the tests to // call the workers directly @@ -290,8 +297,8 @@ export class TestServerReverseProxy { this._proxy.close(); } - private _getRequestHandlerFor(server: TestServer) { - const serverUrl = new URL(server.serverUrl); + private async _getRequestHandlerFor(server: TestServer) { + const serverUrl = new URL(await server.getServerUrl()); return (oreq: express.Request, ores: express.Response) => { log.debug(`[proxy] Requesting (method=${oreq.method}): ${new URL(oreq.url, serverUrl).href}`); From 25041ac6e34fdc12fc1032b131506875269ee8e7 Mon Sep 17 00:00:00 2001 From: fflorent Date: Tue, 14 May 2024 16:20:35 +0200 Subject: [PATCH 3/5] Simplify makeUserApi and remove last skips except one (truly required) --- test/server/lib/DocApi.ts | 68 ++++++++++++++------------- test/server/lib/helpers/TestServer.ts | 22 ++------- 2 files changed, 40 insertions(+), 50 deletions(-) diff --git a/test/server/lib/DocApi.ts b/test/server/lib/DocApi.ts index c27e94d753..08021e4af2 100644 --- a/test/server/lib/DocApi.ts +++ b/test/server/lib/DocApi.ts @@ -75,6 +75,21 @@ function makeConfig(username: string): AxiosRequestConfig { }; } +async function makeUserApi( + org: string, + username: string, + options?: { + headers?: Record, + baseUrl?: string + } +) { + return new UserAPIImpl(`${options?.baseUrl ?? serverUrl}/o/${org}`, { + headers: options?.headers ?? makeConfig(username).headers as Record, + fetch: fetch as unknown as typeof globalThis.fetch, + newFormData: () => new FormData() as any, + }); +} + describe('DocApi', function () { this.timeout(30000); testUtils.setTmpLogLevel('error'); @@ -171,11 +186,16 @@ describe('DocApi', function () { GRIST_SINGLE_PORT: '0', ...overrideEnvConf }; - const home = await TestServer.startServer('home', tmpDir, suitename, additionalEnvConfiguration); - const docs = await TestServer.startServer('docs', tmpDir, suitename, { + + const home = new TestServer('home', tmpDir, suitename); + await home.start(await home.getServerUrl(), additionalEnvConfiguration); + const docs = new TestServer('docs', tmpDir, suitename); + await docs.start(await home.getServerUrl(), { ...additionalEnvConfiguration, APP_DOC_URL: `${await proxy.getServerUrl()}/dw/dw1`, - }, await home.getServerUrl()); + APP_DOC_INTERNAL_URL: await docs.getServerUrl(), + }); + proxy.requireFromOutsideHeader(); await proxy.start(home, docs); @@ -211,11 +231,7 @@ describe('DocApi', function () { }); async function testCompareDocs(proxy: TestServerReverseProxy, home: TestServer) { - const chimpy = makeConfig('chimpy'); - const userApiServerUrl = await proxy.getServerUrl(); - const chimpyApi = await home.makeUserApi( - ORG_NAME, 'chimpy', { serverUrl: userApiServerUrl, headers: chimpy.headers as Record } - ); + const chimpyApi = await makeUserApi(ORG_NAME, 'chimpy'); const ws1 = (await chimpyApi.getOrgWorkspaces('current'))[0].id; const docId1 = await chimpyApi.newDoc({name: 'testdoc1'}, ws1); const docId2 = await chimpyApi.newDoc({name: 'testdoc2'}, ws1); @@ -349,7 +365,7 @@ function testDocApi() { const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; // Make sure kiwi isn't allowed here. await userApi.updateOrgPermissions(ORG_NAME, {users: {[kiwiEmail]: null}}); - const kiwiApi = await home.makeUserApi(ORG_NAME, 'kiwi'); + const kiwiApi = await makeUserApi(ORG_NAME, 'kiwi'); await assert.isRejected(kiwiApi.getWorkspaceAccess(ws1), /Forbidden/); // Add kiwi as an editor for the org. await assert.isRejected(kiwiApi.getOrgAccess(ORG_NAME), /Forbidden/); @@ -369,7 +385,7 @@ function testDocApi() { const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; await userApi.updateOrgPermissions(ORG_NAME, {users: {[kiwiEmail]: null}}); // Make sure kiwi isn't allowed here. - const kiwiApi = await home.makeUserApi(ORG_NAME, 'kiwi'); + const kiwiApi = await makeUserApi(ORG_NAME, 'kiwi'); await assert.isRejected(kiwiApi.getWorkspaceAccess(ws1), /Forbidden/); // Add kiwi as an editor of this workspace. await userApi.updateWorkspacePermissions(ws1, {users: {[kiwiEmail]: 'editors'}}); @@ -388,7 +404,7 @@ function testDocApi() { it("should allow only owners to remove a document", async () => { const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; const doc1 = await userApi.newDoc({name: 'testdeleteme1'}, ws1); - const kiwiApi = await home.makeUserApi(ORG_NAME, 'kiwi'); + const kiwiApi = await makeUserApi(ORG_NAME, 'kiwi'); // Kiwi is editor of the document, so he can't delete it. await userApi.updateDocPermissions(doc1, {users: {'kiwi@getgrist.com': 'editors'}}); @@ -404,7 +420,7 @@ function testDocApi() { it("should allow only owners to rename a document", async () => { const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; const doc1 = await userApi.newDoc({name: 'testrenameme1'}, ws1); - const kiwiApi = await home.makeUserApi(ORG_NAME, 'kiwi'); + const kiwiApi = await makeUserApi(ORG_NAME, 'kiwi'); // Kiwi is editor of the document, so he can't rename it. await userApi.updateDocPermissions(doc1, {users: {'kiwi@getgrist.com': 'editors'}}); @@ -2970,16 +2986,11 @@ function testDocApi() { }); it("document is protected during upload-and-import sequence", async function () { - if (!process.env.TEST_REDIS_URL || home.proxiedServer) { + if (!process.env.TEST_REDIS_URL) { this.skip(); } // Prepare an API for a different user. - const kiwiApi = new UserAPIImpl(`${homeUrl}/o/Fish`, { - headers: {Authorization: 'Bearer api_key_for_kiwi'}, - fetch: fetch as any, - newFormData: () => new FormData() as any, - }); - // upload something for Chimpy and something else for Kiwi. + const kiwiApi = await makeUserApi('Fish', 'kiwi')// upload something for Chimpy and something else for Kiwi. const worker1 = await userApi.getWorkerAPI('import'); const fakeData1 = await testUtils.readFixtureDoc('Hello.grist'); const uploadId1 = await worker1.upload(fakeData1, 'upload.grist'); @@ -3078,12 +3089,11 @@ function testDocApi() { }); it('filters urlIds by org', async function () { - if (home.proxiedServer) { this.skip(); } // Make two documents with same urlId const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; const doc1 = await userApi.newDoc({name: 'testdoc1', urlId: 'urlid'}, ws1); const nasaApi = new UserAPIImpl(`${homeUrl}/o/nasa`, { - headers: {Authorization: 'Bearer api_key_for_chimpy'}, + headers: chimpy.headers as Record, fetch: fetch as any, newFormData: () => new FormData() as any, }); @@ -3111,11 +3121,10 @@ function testDocApi() { it('allows docId access to any document from merged org', async function () { // Make two documents - if (home.proxiedServer) { this.skip(); } const ws1 = (await userApi.getOrgWorkspaces('current'))[0].id; const doc1 = await userApi.newDoc({name: 'testdoc1'}, ws1); const nasaApi = new UserAPIImpl(`${homeUrl}/o/nasa`, { - headers: {Authorization: 'Bearer api_key_for_chimpy'}, + headers: chimpy.headers as Record, fetch: fetch as any, newFormData: () => new FormData() as any, }); @@ -3245,9 +3254,7 @@ function testDocApi() { // Pass kiwi's headers as it contains both Authorization and Origin headers // if run behind a proxy, so we can ensure that the Origin header check is not made. const userApiServerUrl = docs.proxiedServer ? serverUrl : undefined; - const chimpyApi = home.makeUserApi( - ORG_NAME, 'chimpy', { serverUrl: userApiServerUrl, headers: chimpy.headers as Record } - ); + const chimpyApi = await makeUserApi(ORG_NAME, 'chimpy', { baseUrl: userApiServerUrl }); const ws1 = (await chimpyApi.getOrgWorkspaces('current'))[0].id; const docId1 = await chimpyApi.newDoc({name: 'testdoc1'}, ws1); const docId2 = await chimpyApi.newDoc({name: 'testdoc2'}, ws1); @@ -3757,7 +3764,7 @@ function testDocApi() { it("limits daily API usage", async function () { // Make a new document in a test product with a low daily limit - const api = await home.makeUserApi('testdailyapilimit'); + const api = await makeUserApi('testdailyapilimit', 'chimpy'); const workspaceId = await getWorkspaceId(api, 'TestDailyApiLimitWs'); const docId = await api.newDoc({name: 'TestDoc1'}, workspaceId); const max = testDailyApiLimitFeatures.baseMaxApiUnitsPerDocumentPerDay; @@ -3785,7 +3792,7 @@ function testDocApi() { it("limits daily API usage and sets the correct keys in redis", async function () { this.retries(3); // Make a new document in a free team site, currently the only real product which limits daily API usage. - const freeTeamApi = await home.makeUserApi('freeteam'); + const freeTeamApi = await makeUserApi('freeteam', 'chimpy'); const workspaceId = await getWorkspaceId(freeTeamApi, 'FreeTeamWs'); const docId = await freeTeamApi.newDoc({name: 'TestDoc2'}, workspaceId); // Rather than making 5000 requests, set high counts directly for the current and next daily and hourly keys @@ -5357,10 +5364,7 @@ function setup(name: string, cb: () => Promise) { await cb(); // create TestDoc as an empty doc into Private workspace - userApi = api = await home.makeUserApi(ORG_NAME, 'chimpy', { - headers: makeConfig('chimpy').headers as Record, - serverUrl - }); + userApi = api = await makeUserApi(ORG_NAME, 'chimpy'); const wid = await getWorkspaceId(api, 'Private'); docIds.TestDoc = await api.newDoc({name: 'TestDoc'}, wid); }); diff --git a/test/server/lib/helpers/TestServer.ts b/test/server/lib/helpers/TestServer.ts index 151e38357a..d66f0760e9 100644 --- a/test/server/lib/helpers/TestServer.ts +++ b/test/server/lib/helpers/TestServer.ts @@ -73,7 +73,7 @@ export class TestServer { return this._serverUrl; } - public async start(_homeUrl?: string, customEnv?: NodeJS.ProcessEnv, options: {output?: Writable} = {}) { + public async start(homeUrl?: string, customEnv?: NodeJS.ProcessEnv, options: {output?: Writable} = {}) { // put node logs into files with meaningful name that relate to the suite name and server type const fixedName = this._serverTypes.replace(/,/, '_'); const nodeLogPath = path.join(this.rootDir, `${this._suiteName}-${fixedName}-node.log`); @@ -88,16 +88,12 @@ export class TestServer { const serverUrl = await this.getServerUrl(); const port = new URL(serverUrl).port; - const homeUrl = _homeUrl ?? (this._serverTypes.includes('home') ? serverUrl : undefined); const env: NodeJS.ProcessEnv = { APP_HOME_URL: homeUrl, APP_HOME_INTERNAL_URL: homeUrl, GRIST_TESTING_SOCKET: this.testingSocket, GRIST_PORT: port, - ...(this._serverTypes.includes('docs') ? { - APP_DOC_INTERNAL_URL: serverUrl, - }: {}), ...this._defaultEnv, ...customEnv }; @@ -167,19 +163,9 @@ export class TestServer { // Returns the promise for the ChildProcess's signal or exit code. public getExitPromise(): Promise { return this._exitPromise; } - public async makeUserApi( - org: string, - user: string = 'chimpy', - { - headers = {Authorization: `Bearer api_key_for_${user}`}, - serverUrl - }: { - headers?: Record - serverUrl?: string, - } = { headers: undefined, serverUrl: undefined }, - ): Promise { - return new UserAPIImpl(`${serverUrl ?? await this.getServerUrl()}/o/${org}`, { - headers, + public async makeUserApi(org: string, user: string = 'chimpy'): Promise { + return new UserAPIImpl(`${await this.getServerUrl()}/o/${org}`, { + headers: {Authorization: `Bearer api_key_for_${user}`}, fetch: fetch as unknown as typeof globalThis.fetch, newFormData: () => new FormData() as any, }); From 7185cd880642b73053ac5b97e71940710e8b2b7d Mon Sep 17 00:00:00 2001 From: fflorent Date: Tue, 14 May 2024 17:48:34 +0200 Subject: [PATCH 4/5] Fix test "POST /docs/{did}/sql timeout is effective" --- test/server/lib/DocApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/server/lib/DocApi.ts b/test/server/lib/DocApi.ts index 08021e4af2..97127711bb 100644 --- a/test/server/lib/DocApi.ts +++ b/test/server/lib/DocApi.ts @@ -83,7 +83,7 @@ async function makeUserApi( baseUrl?: string } ) { - return new UserAPIImpl(`${options?.baseUrl ?? serverUrl}/o/${org}`, { + return new UserAPIImpl(`${options?.baseUrl ?? homeUrl}/o/${org}`, { headers: options?.headers ?? makeConfig(username).headers as Record, fetch: fetch as unknown as typeof globalThis.fetch, newFormData: () => new FormData() as any, From 03a8c4d03b2cfd6e42782af064c3ab5ca44184e7 Mon Sep 17 00:00:00 2001 From: fflorent Date: Tue, 14 May 2024 17:56:44 +0200 Subject: [PATCH 5/5] Fix linting --- test/server/lib/DocApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/server/lib/DocApi.ts b/test/server/lib/DocApi.ts index 97127711bb..ec7b321940 100644 --- a/test/server/lib/DocApi.ts +++ b/test/server/lib/DocApi.ts @@ -2990,7 +2990,7 @@ function testDocApi() { this.skip(); } // Prepare an API for a different user. - const kiwiApi = await makeUserApi('Fish', 'kiwi')// upload something for Chimpy and something else for Kiwi. + const kiwiApi = await makeUserApi('Fish', 'kiwi'); // upload something for Chimpy and something else for Kiwi. const worker1 = await userApi.getWorkerAPI('import'); const fakeData1 = await testUtils.readFixtureDoc('Hello.grist'); const uploadId1 = await worker1.upload(fakeData1, 'upload.grist');