1
+ /*
2
+ * Copyright 2000-2025 Vaadin Ltd.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ * use this file except in compliance with the License. You may obtain a copy of
6
+ * the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ * License for the specific language governing permissions and limitations under
14
+ * the License.
15
+ */
16
+
17
+ package com.vaadin.gradle
18
+
19
+ import java.io.File
20
+ import java.nio.file.Files
21
+ import java.nio.file.StandardCopyOption
22
+ import kotlin.test.assertContains
23
+ import kotlin.test.assertTrue
24
+ import com.vaadin.flow.gradle.AbstractGradleTest
25
+ import com.vaadin.flow.gradle.expectTaskOutcome
26
+ import org.gradle.testkit.runner.TaskOutcome
27
+ import org.junit.AfterClass
28
+ import org.junit.Before
29
+ import org.junit.BeforeClass
30
+ import org.junit.ClassRule
31
+ import org.junit.Test
32
+ import org.junit.rules.TemporaryFolder
33
+
34
+ class BuildWithoutLicenseTest : AbstractGradleTest () {
35
+
36
+ lateinit var buildInfo: File
37
+
38
+ @Before
39
+ fun setup () {
40
+ buildInfo = testProject.newFile(" output-flow-build-info.json" )
41
+ testProject.buildFile.writeText(
42
+ """
43
+ plugins {
44
+ id 'war'
45
+ id 'com.vaadin.flow'
46
+ }
47
+ repositories {
48
+ maven {
49
+ url = '${realUserHome} /.m2/repository'
50
+ }
51
+ mavenLocal()
52
+ mavenCentral()
53
+ maven { url = 'https://maven.vaadin.com/vaadin-prereleases' }
54
+ flatDir {
55
+ dirs("libs")
56
+ }
57
+ }
58
+ dependencies {
59
+ implementation("com.vaadin:flow:$flowVersion ")
60
+ implementation name:'commercial-addon'
61
+ providedCompile("jakarta.servlet:jakarta.servlet-api:6.0.0")
62
+ implementation("org.slf4j:slf4j-simple:$slf4jVersion ")
63
+ }
64
+
65
+ // Copy the flow-build-info.json so that tests can assert on it
66
+ // after the build.
67
+ tasks.named('vaadinBuildFrontend').configure {
68
+ doLast {
69
+ def mainResourcesDir = project.sourceSets.main.output.resourcesDir
70
+
71
+ // Define source file path based on the resources directory
72
+ def sourceFile = new File(mainResourcesDir, "META-INF/VAADIN/config/flow-build-info.json")
73
+
74
+ if (sourceFile.exists()) {
75
+ def destFile = project.file("${buildInfo.absolutePath} ")
76
+ destFile.text = sourceFile.text
77
+
78
+ logger.lifecycle("Copied flow-build-info.json to temporary file: ${buildInfo.absolutePath} ")
79
+ } else {
80
+ logger.warn("Could not find flow-build-info.json to copy")
81
+ }
82
+ }
83
+ }
84
+ """
85
+ )
86
+ // Add a dependency with commercial marker to trigger license validation
87
+ testProject.newFolder(" libs" )
88
+ val commercialAddonJar: File =
89
+ testProject.newFile(" libs/commercial-addon.jar" )
90
+ Files .copy(
91
+ File (javaClass.classLoader.getResource(" commercial-addon.jar" )!! .path).toPath(),
92
+ commercialAddonJar.toPath(), StandardCopyOption .REPLACE_EXISTING
93
+ )
94
+ }
95
+
96
+ @Test
97
+ fun testBuildFrontendInProductionMode_buildFails () {
98
+
99
+ val result = testProject.buildAndFail(
100
+ " -Duser.home=${testingHomeFolder} " ,
101
+ " -Pvaadin.productionMode" ,
102
+ " vaadinBuildFrontend"
103
+ )
104
+ result.expectTaskOutcome(" vaadinBuildFrontend" , TaskOutcome .FAILED )
105
+ assertContains(
106
+ result.output,
107
+ " Commercial features require a subscription."
108
+ )
109
+ assertContains(result.output, " * vaadin-commercial-component" )
110
+ assertContains(result.output, " commercialWithWatermark" )
111
+ }
112
+
113
+ @Test
114
+ fun testBuildFrontendInProductionMode_watermarkBuildDisabled_buildFails () {
115
+ testProject.buildFile.appendText(
116
+ """
117
+ vaadin {
118
+ commercialWithWatermark = false
119
+ }
120
+ """ .trimIndent()
121
+ )
122
+ val result = testProject.buildAndFail(
123
+ " -Duser.home=${testingHomeFolder} " ,
124
+ " -Pvaadin.productionMode" ,
125
+ " vaadinBuildFrontend"
126
+ )
127
+ result.expectTaskOutcome(" vaadinBuildFrontend" , TaskOutcome .FAILED )
128
+ assertContains(
129
+ result.output,
130
+ " Commercial features require a subscription."
131
+ )
132
+ assertContains(result.output, " * vaadin-commercial-component" )
133
+ assertContains(result.output, " commercialWithWatermark" )
134
+ }
135
+
136
+ @Test
137
+ fun testBuildFrontendInProductionMode_watermarkBuildEnabledBySystemProperty_buildSucceeds () {
138
+
139
+ val result = testProject.build(
140
+ " -Duser.home=${testingHomeFolder} " ,
141
+ " -DcommercialWithWatermark" ,
142
+ " -Pvaadin.productionMode" ,
143
+ " vaadinBuildFrontend"
144
+ )
145
+ result.expectTaskOutcome(" vaadinBuildFrontend" , TaskOutcome .SUCCESS )
146
+ assertContains(result.output, " Application watermark enabled" )
147
+
148
+ assertTrue { buildInfo.exists() }
149
+ val buildInfoJson = buildInfo.readText()
150
+ assertContains(
151
+ buildInfoJson,
152
+ Regex (" (?s).*\" watermark\\ .enable\"\\ s*:\\ s*true.*" ),
153
+ " watermark.enable token missing or incorrect in ${buildInfo.absolutePath} : ${buildInfoJson} "
154
+ )
155
+ }
156
+
157
+ @Test
158
+ fun testBuildFrontendInProductionMode_watermarkBuildEnabled_buildSucceeds () {
159
+ testProject.buildFile.appendText(
160
+ """
161
+ vaadin {
162
+ commercialWithWatermark = true
163
+ }
164
+ """ .trimIndent()
165
+ )
166
+ val result = testProject.build(
167
+ " -Duser.home=${testingHomeFolder} " ,
168
+ " -Pvaadin.productionMode" ,
169
+ " vaadinBuildFrontend"
170
+ )
171
+ result.expectTaskOutcome(" vaadinBuildFrontend" , TaskOutcome .SUCCESS )
172
+ assertContains(result.output, " Application watermark enabled" )
173
+
174
+ assertTrue { buildInfo.exists() }
175
+ val buildInfoJson = buildInfo.readText()
176
+ assertContains(
177
+ buildInfoJson,
178
+ Regex (" (?s).*\" watermark\\ .enable\"\\ s*:\\ s*true.*" ),
179
+ " watermark.enable token missing or incorrect in ${buildInfo.absolutePath} : ${buildInfoJson} "
180
+ )
181
+ }
182
+
183
+ @Test
184
+ fun testBuildFrontendInProductionMode_watermarkBuildEnabledByGradleProperty_buildSucceeds () {
185
+ val result = testProject.build(
186
+ " -Duser.home=${testingHomeFolder} " ,
187
+ " -Pvaadin.commercialWithWatermark" ,
188
+ " -Pvaadin.productionMode" ,
189
+ " vaadinBuildFrontend"
190
+ )
191
+ result.expectTaskOutcome(" vaadinBuildFrontend" , TaskOutcome .SUCCESS )
192
+ assertContains(result.output, " Application watermark enabled" )
193
+
194
+ assertTrue { buildInfo.exists() }
195
+ val buildInfoJson = buildInfo.readText()
196
+ assertContains(
197
+ buildInfoJson,
198
+ Regex (" (?s).*\" watermark\\ .enable\"\\ s*:\\ s*true.*" ),
199
+ " watermark.enable token missing or incorrect in ${buildInfo.absolutePath} : ${buildInfoJson} "
200
+ )
201
+
202
+ }
203
+
204
+ companion object {
205
+
206
+ @ClassRule
207
+ @JvmField
208
+ val tempHomeFolder = TemporaryFolder ()
209
+ lateinit var realUserHome: String
210
+ lateinit var testingHomeFolder: String
211
+
212
+ @BeforeClass
213
+ @JvmStatic
214
+ fun createFakeHome () {
215
+ realUserHome = System .getProperty(" user.home" );
216
+ val userHomeFolder = File (realUserHome)
217
+ val vaadinHomeNodeFolder =
218
+ userHomeFolder.resolve(" .vaadin" ).resolve(" node" )
219
+ // Try to speed up test by copying existing node into the fake home
220
+ if (vaadinHomeNodeFolder.isDirectory) {
221
+ val fakeVaadinHomeNode =
222
+ tempHomeFolder.root.resolve(" .vaadin" ).resolve(" node" )
223
+ fakeVaadinHomeNode.mkdirs();
224
+ vaadinHomeNodeFolder.copyRecursively(fakeVaadinHomeNode);
225
+ // copyRecursively does not preserve file attributes
226
+ // fix it by manually setting executable flag so that node can
227
+ // be launched
228
+ vaadinHomeNodeFolder.walkTopDown().filter {
229
+ it.canExecute()
230
+ }.forEach {
231
+ val relative = it.relativeTo(vaadinHomeNodeFolder)
232
+ val destination = fakeVaadinHomeNode.resolve(relative.path)
233
+ destination.setExecutable(true )
234
+ }
235
+ }
236
+ testingHomeFolder = tempHomeFolder.root.absolutePath
237
+ System .setProperty(" user.home" , testingHomeFolder)
238
+ }
239
+
240
+ @AfterClass
241
+ @JvmStatic
242
+ fun restoreUserHomeSystemProperty () {
243
+ System .setProperty(" user.home" , realUserHome)
244
+ }
245
+
246
+ }
247
+
248
+ }
0 commit comments