Explorar o código

Merge pull request #18893 from overleaf/msm-sp-e2e-native-run

[CE/SP] Added `test-e2e-native` runner

GitOrigin-RevId: a123b2a83a47566a091acc37ccef6c4895bc9949
Miguel Serrano %!s(int64=2) %!d(string=hai) anos
pai
achega
6ba61f19f4

+ 4 - 0
server-ce/test/Makefile

@@ -10,6 +10,10 @@ export TEX_LIVE_DOCKER_IMAGE ?= quay.io/sharelatex/texlive-full:2023.1
 export ALL_TEX_LIVE_DOCKER_IMAGES ?= quay.io/sharelatex/texlive-full:2023.1,quay.io/sharelatex/texlive-full:2022.1
 export IMAGE_TAG_PRO ?= quay.io/sharelatex/sharelatex-pro:latest
 
+test-e2e-native:
+	docker compose -f docker-compose.yml -f docker-compose.native.yml up --build --no-log-prefix sharelatex host-admin -d
+	CYPRESS_ADMIN_CLIENT_URL='http://localhost:8081' CYPRESS_GIT_BRIDGE_PUBLIC_HOST='localhost' npm run cypress:open
+
 test-e2e:
 	docker compose up --build --no-log-prefix --exit-code-from=e2e e2e
 

+ 14 - 0
server-ce/test/docker-compose.native.yml

@@ -0,0 +1,14 @@
+version: '2.2'
+services:
+  sharelatex:
+    ports:
+      - "127.0.0.1:80:80"
+    environment:
+      OVERLEAF_SITE_URL: 'http://localhost'
+
+  host-admin:
+    ports:
+      - "127.0.0.1:8081:80"
+    environment:
+      NATIVE_CYPRESS: 'true'
+      ACCESS_CONTROL_ALLOW_ORIGIN: 'http://localhost'

+ 10 - 3
server-ce/test/git-bridge.spec.ts

@@ -15,6 +15,9 @@ describe('git-bridge', function () {
     V1_HISTORY_URL: 'http://sharelatex:3100/api',
   }
 
+  const gitBridgePublicHost =
+    Cypress.env('GIT_BRIDGE_PUBLIC_HOST') || 'sharelatex'
+
   describe('enabled in Server Pro', function () {
     startWith({
       pro: true,
@@ -74,7 +77,9 @@ describe('git-bridge', function () {
       cy.findByText('Git').click()
       cy.findByRole('dialog').within(() => {
         cy.get('@projectId').then(id => {
-          cy.get('code').contains(`git clone http://git@sharelatex/git/${id}`)
+          cy.get('code').contains(
+            `git clone http://git@${gitBridgePublicHost}/git/${id}`
+          )
         })
         cy.findByRole('button', {
           name: 'Generate token',
@@ -88,7 +93,9 @@ describe('git-bridge', function () {
       cy.findByText('Git').click()
       cy.findByRole('dialog').within(() => {
         cy.get('@projectId').then(id => {
-          cy.get('code').contains(`git clone http://git@sharelatex/git/${id}`)
+          cy.get('code').contains(
+            `git clone http://git@${gitBridgePublicHost}/git/${id}`
+          )
         })
         cy.findByText('Generate token').should('not.exist')
         cy.findByText(/generate a new one in Account Settings/)
@@ -109,7 +116,7 @@ describe('git-bridge', function () {
       cy.get('@projectId').then(projectId => {
         cy.findByRole('dialog').within(() => {
           cy.get('code').contains(
-            `git clone http://git@sharelatex/git/${projectId}`
+            `git clone http://git@${gitBridgePublicHost}/git/${projectId}`
           )
         })
         cy.findByRole('button', {

+ 7 - 5
server-ce/test/helpers/hostAdminClient.ts

@@ -1,5 +1,7 @@
+const hostAdminUrl = Cypress.env('ADMIN_CLIENT_URL') || 'http://host-admin'
+
 export async function dockerCompose(cmd: string, ...args: string[]) {
-  return await fetchJSON(`http://host-admin/docker/compose/${cmd}`, {
+  return await fetchJSON(`${hostAdminUrl}/docker/compose/${cmd}`, {
     method: 'POST',
     body: JSON.stringify({
       args,
@@ -8,13 +10,13 @@ export async function dockerCompose(cmd: string, ...args: string[]) {
 }
 
 export async function mongoInit() {
-  return await fetchJSON('http://host-admin/mongo/init', {
+  return await fetchJSON(`${hostAdminUrl}/mongo/init`, {
     method: 'POST',
   })
 }
 
 export async function resetData() {
-  return await fetchJSON('http://host-admin/reset/data', {
+  return await fetchJSON(`${hostAdminUrl}/reset/data`, {
     method: 'POST',
   })
 }
@@ -25,7 +27,7 @@ export async function reconfigure({
   vars = {},
   withDataDir = false,
 }) {
-  return await fetchJSON('http://host-admin/reconfigure', {
+  return await fetchJSON(`${hostAdminUrl}/reconfigure`, {
     method: 'POST',
     body: JSON.stringify({
       pro,
@@ -65,7 +67,7 @@ export async function runScript({
   script: string
   args?: string[]
 }) {
-  return await fetchJSON('http://host-admin/run/script', {
+  return await fetchJSON(`${hostAdminUrl}/run/script`, {
     method: 'POST',
     body: JSON.stringify({
       cwd,

+ 33 - 23
server-ce/test/host-admin.js

@@ -11,7 +11,9 @@ const {
 const YAML = require('js-yaml')
 
 const PATHS = {
+  DOCKER_COMPOSE_FILE: 'docker-compose.yml',
   DOCKER_COMPOSE_OVERRIDE: 'docker-compose.override.yml',
+  DOCKER_COMPOSE_NATIVE: 'docker-compose.native.yml',
   DATA_DIR: Path.join(__dirname, 'data'),
   SANDBOXED_COMPILES_HOST_DIR: Path.join(__dirname, 'data/compiles'),
 }
@@ -44,6 +46,17 @@ function writeDockerComposeOverride(cfg) {
   fs.writeFileSync(PATHS.DOCKER_COMPOSE_OVERRIDE, YAML.dump(cfg))
 }
 
+function runDockerCompose(command, args, callback) {
+  const files = ['-f', PATHS.DOCKER_COMPOSE_FILE]
+  if (process.env.NATIVE_CYPRESS) {
+    files.push('-f', PATHS.DOCKER_COMPOSE_NATIVE)
+  }
+  if (fs.existsSync(PATHS.DOCKER_COMPOSE_OVERRIDE)) {
+    files.push('-f', PATHS.DOCKER_COMPOSE_OVERRIDE)
+  }
+  execFile('docker', ['compose', ...files, command, ...args], callback)
+}
+
 function purgeDataDir() {
   fs.rmSync(PATHS.DATA_DIR, { recursive: true, force: true })
 }
@@ -58,7 +71,9 @@ app.use((req, res, next) => {
   // Basic access logs
   console.log(req.method, req.url, req.body)
   // Add CORS headers
-  res.setHeader('Access-Control-Allow-Origin', 'http://sharelatex')
+  const accessControlAllowOrigin =
+    process.env.ACCESS_CONTROL_ALLOW_ORIGIN || 'http://sharelatex'
+  res.setHeader('Access-Control-Allow-Origin', accessControlAllowOrigin)
   res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
   res.setHeader('Access-Control-Max-Age', '3600')
   next()
@@ -79,11 +94,9 @@ app.post(
   (req, res) => {
     const { cwd, script, args } = req.body
 
-    execFile(
-      'docker',
+    runDockerCompose(
+      'exec',
       [
-        'compose',
-        'exec',
         'sharelatex',
         'bash',
         '-c',
@@ -204,24 +217,22 @@ app.post(
     if (['stop', 'down'].includes(cmd)) {
       mongoIsInitialized = false
     }
-    execFile('docker', ['compose', cmd, ...args], (error, stdout, stderr) => {
+    runDockerCompose(cmd, args, (error, stdout, stderr) => {
       res.json({ error, stdout, stderr })
     })
   }
 )
 
 function mongoInit(callback) {
-  execFile(
-    'docker',
-    ['compose', 'up', '--detach', '--wait', 'mongo'],
+  runDockerCompose(
+    'up',
+    ['--detach', '--wait', 'mongo'],
     (error, stdout, stderr) => {
       if (error) return callback(error, stdout, stderr)
 
-      execFile(
-        'docker',
+      runDockerCompose(
+        'exec',
         [
-          'compose',
-          'exec',
           'mongo',
           'mongo',
           '--eval',
@@ -268,10 +279,9 @@ app.post(
     const doMongoInit = mongoIsInitialized ? cb => cb() : mongoInit
     doMongoInit((error, stdout, stderr) => {
       if (error) return res.json({ error, stdout, stderr })
-
-      execFile(
-        'docker',
-        ['compose', 'up', '--detach', '--wait', 'sharelatex'],
+      runDockerCompose(
+        'up',
+        ['--detach', '--wait', 'sharelatex'],
         (error, stdout, stderr) => {
           res.json({ error, stdout, stderr })
         }
@@ -281,9 +291,9 @@ app.post(
 )
 
 app.post('/reset/data', (req, res) => {
-  execFile(
-    'docker',
-    ['compose', 'stop', '--timeout=0', 'sharelatex'],
+  runDockerCompose(
+    'stop',
+    ['--timeout=0', 'sharelatex'],
     (error, stdout, stderr) => {
       if (error) return res.json({ error, stdout, stderr })
 
@@ -294,9 +304,9 @@ app.post('/reset/data', (req, res) => {
       }
 
       mongoIsInitialized = false
-      execFile(
-        'docker',
-        ['compose', 'down', '--timeout=0', '--volumes', 'mongo', 'redis'],
+      runDockerCompose(
+        'down',
+        ['--timeout=0', '--volumes', 'mongo', 'redis'],
         (error, stdout, stderr) => {
           res.json({ error, stdout, stderr })
         }