From 6c1a9f286f88766ab4bdd755b3fd97d383d91bb2 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 25 Aug 2020 08:42:16 +0200 Subject: [PATCH] Make stage concept accessible from ui --- scm-ui/ui-components/src/devBuild.test.ts | 20 ++++++++++++------- scm-ui/ui-components/src/devBuild.ts | 3 ++- scm-ui/ui-scripts/src/webpack.config.js | 15 +++++++++----- scm-ui/ui-webapp/public/index.mustache | 1 + .../scm/TemplatingPushStateDispatcher.java | 20 +++++++++++++------ .../scm/PushStateDispatcherProviderTest.java | 7 +++++-- .../TemplatingPushStateDispatcherTest.java | 10 ++++++++-- 7 files changed, 53 insertions(+), 23 deletions(-) diff --git a/scm-ui/ui-components/src/devBuild.test.ts b/scm-ui/ui-components/src/devBuild.test.ts index 8df47ec6ee..5964032f53 100644 --- a/scm-ui/ui-components/src/devBuild.test.ts +++ b/scm-ui/ui-components/src/devBuild.test.ts @@ -25,31 +25,37 @@ import { createAttributesForTesting, isDevBuild } from "./devBuild"; describe("devbuild tests", () => { - let env: string | undefined; + let stage: string | undefined; + + const setStage = (s?: string) => { + // @ts-ignore scmStage is set on the index page + window.scmStage = s; + }; beforeAll(() => { - env = process.env.NODE_ENV; + // @ts-ignore scmStage is set on the index page + stage = window.scmStage; }); afterAll(() => { - process.env.NODE_ENV = env; + setStage(stage); }); describe("isDevBuild tests", () => { it("should return true for development", () => { - process.env.NODE_ENV = "development"; + setStage("development"); expect(isDevBuild()).toBe(true); }); it("should return false for production", () => { - process.env.NODE_ENV = "production"; + setStage("production"); expect(isDevBuild()).toBe(false); }); }); describe("createAttributesForTesting in non development mode", () => { beforeAll(() => { - process.env.NODE_ENV = "production"; + setStage("production"); }); it("should return undefined for non development", () => { @@ -60,7 +66,7 @@ describe("devbuild tests", () => { describe("createAttributesForTesting in development mode", () => { beforeAll(() => { - process.env.NODE_ENV = "development"; + setStage("development"); }); it("should return undefined for non development", () => { diff --git a/scm-ui/ui-components/src/devBuild.ts b/scm-ui/ui-components/src/devBuild.ts index abf1a18dc7..4425f695ab 100644 --- a/scm-ui/ui-components/src/devBuild.ts +++ b/scm-ui/ui-components/src/devBuild.ts @@ -22,7 +22,8 @@ * SOFTWARE. */ -export const isDevBuild = () => process.env.NODE_ENV === "development"; +// @ts-ignore scmStage is set on the index page +export const isDevBuild = () => (window.scmStage || "").toUpperCase() === "DEVELOPMENT"; export const createAttributesForTesting = (testId?: string) => { if (!testId || !isDevBuild()) { diff --git a/scm-ui/ui-scripts/src/webpack.config.js b/scm-ui/ui-scripts/src/webpack.config.js index f25e6c3122..0bc9f93fd7 100644 --- a/scm-ui/ui-scripts/src/webpack.config.js +++ b/scm-ui/ui-scripts/src/webpack.config.js @@ -22,12 +22,13 @@ * SOFTWARE. */ const path = require("path"); -const createIndexMiddleware = require("./middleware/IndexMiddleware"); -const createContextPathMiddleware = require("./middleware/ContextPathMiddleware"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const WorkerPlugin = require("worker-plugin"); +const createIndexMiddleware = require("./middleware/IndexMiddleware"); +const createContextPathMiddleware = require("./middleware/ContextPathMiddleware"); + const isDevelopment = process.env.NODE_ENV === "development"; const root = path.resolve(process.cwd(), "scm-ui"); @@ -39,6 +40,8 @@ let mode = "production"; if (isDevelopment) { mode = "development"; babelPlugins.push(require.resolve("react-refresh/babel")); + // it is ok to use require here, because we want to load the package conditionally + // eslint-disable-next-line global-require const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin"); webpackPlugins.push(new ReactRefreshWebpackPlugin()); } @@ -113,13 +116,15 @@ module.exports = [ historyApiFallback: true, overlay: true, port: 3000, - before: function(app) { + before: app => { app.use(createContextPathMiddleware("/scm")); }, - after: function(app) { + after: app => { const templatePath = path.join(root, "ui-webapp", "public", "index.mustache"); + const stage = process.env.NODE_ENV || "DEVELOPMENT"; const renderParams = { - contextPath: "/scm" + contextPath: "/scm", + scmStage: stage.toUpperCase() }; app.use(createIndexMiddleware(templatePath, renderParams)); }, diff --git a/scm-ui/ui-webapp/public/index.mustache b/scm-ui/ui-webapp/public/index.mustache index d94bc552ee..3c0a51713c 100644 --- a/scm-ui/ui-webapp/public/index.mustache +++ b/scm-ui/ui-webapp/public/index.mustache @@ -47,6 +47,7 @@ --> diff --git a/scm-webapp/src/main/java/sonia/scm/TemplatingPushStateDispatcher.java b/scm-webapp/src/main/java/sonia/scm/TemplatingPushStateDispatcher.java index 72f451f614..decc6a09c5 100644 --- a/scm-webapp/src/main/java/sonia/scm/TemplatingPushStateDispatcher.java +++ b/scm-webapp/src/main/java/sonia/scm/TemplatingPushStateDispatcher.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm; import com.google.common.annotations.VisibleForTesting; @@ -46,15 +46,17 @@ public class TemplatingPushStateDispatcher implements PushStateDispatcher { static final String TEMPLATE = "/index.mustache"; private final TemplateEngine templateEngine; + private final SCMContextProvider context; @Inject - public TemplatingPushStateDispatcher(TemplateEngineFactory templateEngineFactory) { - this(templateEngineFactory.getDefaultEngine()); + public TemplatingPushStateDispatcher(TemplateEngineFactory templateEngineFactory, SCMContextProvider context) { + this(templateEngineFactory.getDefaultEngine(), context); } @VisibleForTesting - TemplatingPushStateDispatcher(TemplateEngine templateEngine) { + TemplatingPushStateDispatcher(TemplateEngine templateEngine, SCMContextProvider context) { this.templateEngine = templateEngine; + this.context = context; } @Override @@ -64,7 +66,7 @@ public class TemplatingPushStateDispatcher implements PushStateDispatcher { Template template = templateEngine.getTemplate(TEMPLATE); try (Writer writer = response.getWriter()) { - template.execute(writer, new IndexHtmlModel(request)); + template.execute(writer, new IndexHtmlModel(request, context.getStage())); } } @@ -72,15 +74,21 @@ public class TemplatingPushStateDispatcher implements PushStateDispatcher { static class IndexHtmlModel { private final HttpServletRequest request; + private final Stage scmStage; - private IndexHtmlModel(HttpServletRequest request) { + private IndexHtmlModel(HttpServletRequest request, Stage scmStage) { this.request = request; + this.scmStage = scmStage; } public String getContextPath() { return request.getContextPath(); } + public String getScmStage() { + return scmStage.name(); + } + public String getLiveReloadURL() { return System.getProperty("livereload.url"); } diff --git a/scm-webapp/src/test/java/sonia/scm/PushStateDispatcherProviderTest.java b/scm-webapp/src/test/java/sonia/scm/PushStateDispatcherProviderTest.java index ba3cf66c02..4ad89d1907 100644 --- a/scm-webapp/src/test/java/sonia/scm/PushStateDispatcherProviderTest.java +++ b/scm-webapp/src/test/java/sonia/scm/PushStateDispatcherProviderTest.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm; import com.google.inject.util.Providers; @@ -39,8 +39,11 @@ public class PushStateDispatcherProviderTest { @Mock private TemplateEngine templateEngine; + @Mock + private SCMContextProvider context; + private PushStateDispatcherProvider provider = new PushStateDispatcherProvider( - Providers.of(new TemplatingPushStateDispatcher(templateEngine)) + Providers.of(new TemplatingPushStateDispatcher(templateEngine, context)) ); @Test diff --git a/scm-webapp/src/test/java/sonia/scm/TemplatingPushStateDispatcherTest.java b/scm-webapp/src/test/java/sonia/scm/TemplatingPushStateDispatcherTest.java index a8dcffc196..b20520ea72 100644 --- a/scm-webapp/src/test/java/sonia/scm/TemplatingPushStateDispatcherTest.java +++ b/scm-webapp/src/test/java/sonia/scm/TemplatingPushStateDispatcherTest.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm; import org.junit.Before; @@ -61,18 +61,24 @@ public class TemplatingPushStateDispatcherTest { @Mock private Template template; + @Mock + private SCMContextProvider context; + private TemplatingPushStateDispatcher dispatcher; @Before public void setUpMocks() { - dispatcher = new TemplatingPushStateDispatcher(templateEngine); + dispatcher = new TemplatingPushStateDispatcher(templateEngine, context); } @Test public void testDispatch() throws IOException { + when(context.getStage()).thenReturn(Stage.DEVELOPMENT); + TemplatingPushStateDispatcher.IndexHtmlModel model = dispatch(); assertEquals("/scm", model.getContextPath()); assertNull(model.getLiveReloadURL()); + assertEquals("DEVELOPMENT", model.getScmStage()); } @Test