Skip to content

Commit caf8dde

Browse files
committed
feat: add support for npm based cli tests
1 parent 9564bf2 commit caf8dde

File tree

8 files changed

+145
-33
lines changed

8 files changed

+145
-33
lines changed

cli/build.gradle

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,11 @@ def nativeCompileMetaDir = project.layout.buildDirectory.dir('nativeCompile/src/
102102
// use tasks 'nativeCompile' and 'nativeRun' to compile and run the native image
103103
graalvmNative {
104104
agent {
105-
enabled = true // we would love to make this dynamic, but it's not possible
105+
enabled = !project.hasProperty('skipGraalAgent') // we would love to make this dynamic, but it's not possible
106106
defaultMode = "standard"
107107
metadataCopy {
108108
inputTaskNames.add('test')
109+
inputTaskNames.add('testNpm')
109110
mergeWithExisting = false
110111
outputDirectories.add(nativeCompileMetaDir.get().asFile.path)
111112
}
@@ -114,7 +115,7 @@ graalvmNative {
114115
boolean test(Task task) {
115116
// if (project.hasProperty('agent')) {
116117
println ("Instrumenting task: " + task.name + " " + task.name == 'test' + "proj: " + task.project.hasProperty('agent'))
117-
return task.name == 'test'
118+
return task.name == 'test' || task.name == 'testNpm'
118119
// }
119120
// return false
120121
}
@@ -148,7 +149,7 @@ graalvmNative {
148149

149150

150151
tasks.named('metadataCopy') {
151-
dependsOn('test')
152+
dependsOn('test', 'testNpm')
152153
}
153154

154155
tasks.named('nativeCompile') {
@@ -174,17 +175,17 @@ gradle.taskGraph.whenReady { TaskExecutionGraph graph ->
174175
}
175176

176177
tasks.withType(Test).configureEach {
177-
if (it.name == 'test') {
178+
if (it.name == 'test' || it.name == 'testNpm') {
178179
it.outputs.dir(nativeCompileMetaDir)
179180
if (project.hasProperty('agent')) {
180181
it.inputs.property('agent', project.property('agent')) // make sure to re-run tests if agent changes
181182
}
182183
}
183-
if (it.name == 'testCliProcess') {
184+
if (it.name == 'testCliProcess' || it.name == 'testCliProcessNpm') {
184185
it.dependsOn('shadowJar')
185186
it.systemProperty 'spotless.cli.shadowJar', tasks.shadowJar.archiveFile.get().asFile
186187
}
187-
if (it.name == 'testCliNative') {
188+
if (it.name == 'testCliNative' || it.name == 'testCliNativeNpm') {
188189
it.dependsOn('nativeCompile')
189190
it.systemProperty 'spotless.cli.nativeImage', tasks.nativeCompile.outputFile.get().asFile
190191
}

cli/src/main/java/com/diffplug/spotless/cli/core/ExecutionLayout.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Optional;
2323

2424
import javax.annotation.Nonnull;
25+
import javax.annotation.Nullable;
2526

2627
import com.diffplug.spotless.cli.steps.BuildDirGloballyReusable;
2728
import com.diffplug.spotless.cli.steps.SpotlessCLIFormatterStep;
@@ -32,17 +33,20 @@ public class ExecutionLayout {
3233
private final SpotlessCommandLineStream commandLineStream;
3334
private final ChecksumCalculator checksumCalculator;
3435

35-
private ExecutionLayout(@Nonnull FileResolver fileResolver, SpotlessCommandLineStream commandLineStream) {
36+
private ExecutionLayout(@Nonnull FileResolver fileResolver, @Nonnull SpotlessCommandLineStream commandLineStream) {
3637
this.fileResolver = Objects.requireNonNull(fileResolver);
37-
this.commandLineStream = commandLineStream;
38+
this.commandLineStream = Objects.requireNonNull(commandLineStream);
3839
this.checksumCalculator = new ChecksumCalculator();
3940
}
4041

41-
public static ExecutionLayout create(FileResolver fileResolver, SpotlessCommandLineStream commandLineStream) {
42+
public static ExecutionLayout create(@Nonnull FileResolver fileResolver, @Nonnull SpotlessCommandLineStream commandLineStream) {
4243
return new ExecutionLayout(fileResolver, commandLineStream);
4344
}
4445

45-
public Optional<Path> find(Path searchPath) {
46+
public Optional<Path> find(@Nullable Path searchPath) {
47+
if (searchPath == null) {
48+
return Optional.empty();
49+
}
4650
Path found = fileResolver.resolvePath(searchPath);
4751
if (found.toFile().canRead()) {
4852
return Optional.of(found);

cli/src/main/java/com/diffplug/spotless/cli/steps/Prettier.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
import java.io.File;
2424
import java.nio.file.Path;
2525
import java.util.Collections;
26+
import java.util.LinkedHashMap;
2627
import java.util.List;
2728
import java.util.Map;
2829
import java.util.Objects;
2930

3031
import javax.annotation.Nonnull;
31-
import javax.annotation.Nullable;
3232

3333
import com.diffplug.spotless.FormatterStep;
3434
import com.diffplug.spotless.cli.core.ExecutionLayout;
@@ -64,7 +64,7 @@ public class Prettier extends SpotlessFormatterStep {
6464
Path prettierConfigPath;
6565

6666
@CommandLine.Option(names = {"--prettier-config-option", "-c"}, description = "The Prettier configuration options.")
67-
Map<String, Object> prettierConfigOptions;
67+
Map<String, String> prettierConfigOptions;
6868

6969
@Nonnull
7070
@Override
@@ -76,7 +76,7 @@ public List<FormatterStep> prepareFormatterSteps(SpotlessActionContext context)
7676
.withExplicitNodeExecutable(explicitNodeExecutable)
7777
.withExplicitNpmrcFile(explicitNpmrcFile)
7878
.withAdditionalNpmrcLocations(additionalNpmrcLocations())
79-
.withPrettierConfigOptions(prettierConfigOptions)
79+
.withPrettierConfigOptions(prettierConfigOptions())
8080
.withPrettierConfigPath(prettierConfigPath)
8181
.build();
8282

@@ -85,24 +85,30 @@ public List<FormatterStep> prepareFormatterSteps(SpotlessActionContext context)
8585
return List.of(prettierFormatterStep);
8686
}
8787

88-
private static FormatterStep adapt(FormatterStep step) {
89-
return new FormatterStep() {
90-
@Override
91-
public String getName() {
92-
return step.getName();
93-
}
94-
95-
@Nullable
96-
@Override
97-
public String format(String rawUnix, File file) throws Exception {
98-
return step.format(rawUnix, file);
88+
private Map<String, Object> prettierConfigOptions() {
89+
if (prettierConfigOptions == null) {
90+
return Collections.emptyMap();
91+
}
92+
Map<String, Object> normalized = new LinkedHashMap<>();
93+
prettierConfigOptions.forEach((key, value) -> {
94+
if (value == null) {
95+
normalized.put(key, null);
96+
} else {
97+
normalized.put(key, normalizePrettierOption(key, value));
9998
}
99+
});
100+
return normalized;
101+
}
100102

101-
@Override
102-
public void close() throws Exception {
103-
step.close();
104-
}
105-
};
103+
private Object normalizePrettierOption(String key, String value) {
104+
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
105+
return Boolean.parseBoolean(value);
106+
}
107+
try {
108+
return Integer.parseInt(value);
109+
} catch (NumberFormatException e) {
110+
return value;
111+
}
106112
}
107113

108114
private Map<String, String> devDependencies() {
@@ -205,7 +211,7 @@ public FormatterStep build() {
205211
asFile(explicitNpmrcFile),
206212
asFiles(additionalNpmrcLocations)),
207213
new PrettierConfig(
208-
asFile(prettierConfigPath),
214+
asFile(prettierConfigPath != null ? layout.find(prettierConfigPath).orElseThrow() : null),
209215
prettierConfigOptions));
210216
return step;
211217
}

cli/src/test/java/com/diffplug/spotless/cli/CLIIntegrationHarness.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import org.junit.jupiter.api.BeforeEach;
2121

2222
import com.diffplug.spotless.ResourceHarness;
23+
import com.diffplug.spotless.tag.CliNativeNpmTest;
2324
import com.diffplug.spotless.tag.CliNativeTest;
25+
import com.diffplug.spotless.tag.CliProcessNpmTest;
2426
import com.diffplug.spotless.tag.CliProcessTest;
2527

2628
public abstract class CLIIntegrationHarness extends ResourceHarness {
@@ -51,11 +53,13 @@ protected SpotlessCLIRunner cliRunner() {
5153

5254
private SpotlessCLIRunner createRunnerForTag() {
5355
CliProcessTest cliProcessTest = getClass().getAnnotation(CliProcessTest.class);
54-
if (cliProcessTest != null) {
56+
CliProcessNpmTest cliProcessNpmTest = getClass().getAnnotation(CliProcessNpmTest.class);
57+
if (cliProcessTest != null || cliProcessNpmTest != null) {
5558
return SpotlessCLIRunner.createExternalProcess();
5659
}
5760
CliNativeTest cliNativeTest = getClass().getAnnotation(CliNativeTest.class);
58-
if (cliNativeTest != null) {
61+
CliNativeNpmTest cliNativeNpmTest = getClass().getAnnotation(CliNativeNpmTest.class);
62+
if (cliNativeTest != null || cliNativeNpmTest != null) {
5963
return SpotlessCLIRunner.createNative();
6064
}
6165
return SpotlessCLIRunner.create();

cli/src/test/java/com/diffplug/spotless/cli/steps/PrettierTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,45 @@
1515
*/
1616
package com.diffplug.spotless.cli.steps;
1717

18+
import java.io.IOException;
19+
20+
import org.junit.jupiter.api.Test;
21+
1822
import com.diffplug.spotless.cli.CLIIntegrationHarness;
23+
import com.diffplug.spotless.cli.SpotlessCLIRunner;
24+
import com.diffplug.spotless.tag.NpmTest;
1925

26+
@NpmTest
2027
public class PrettierTest extends CLIIntegrationHarness {
2128

2229
// TODO
2330

31+
@Test
32+
void itRunsPrettierForTsFilesWithOptions() throws IOException {
33+
setFile("test.ts").toResource("npm/prettier/config/typescript.dirty");
34+
35+
SpotlessCLIRunner.Result result = cliRunner()
36+
.withTargets("test.ts")
37+
.withStep(Prettier.class)
38+
.withOption("--prettier-config-option", "printWidth=20")
39+
.withOption("--prettier-config-option", "parser=typescript")
40+
.run();
41+
42+
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile_prettier_2.clean");
43+
}
44+
45+
@Test
46+
void itRunsPrettierForTsFilesWithOptionFile() throws Exception {
47+
setFile(".prettierrc.yml").toResource("npm/prettier/config/.prettierrc.yml");
48+
setFile("test.ts").toResource("npm/prettier/config/typescript.dirty");
49+
50+
SpotlessCLIRunner.Result result = cliRunner()
51+
.withTargets("test.ts")
52+
.withStep(Prettier.class)
53+
.withOption("--prettier-config-path", ".prettierrc.yml")
54+
.run();
55+
56+
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile_prettier_2.clean");
57+
}
58+
2459
}

gradle/special-tests.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ def special = [
99
'npm',
1010
'shfmt',
1111
'cliProcess',
12-
'cliNative'
12+
'cliProcessNpm',
13+
'cliNative',
14+
'cliNativeNpm'
1315
]
1416

1517
boolean isCiServer = System.getenv().containsKey("CI")
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2021-2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of 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,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.tag;
17+
18+
import static java.lang.annotation.ElementType.METHOD;
19+
import static java.lang.annotation.ElementType.TYPE;
20+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
21+
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.Target;
24+
25+
import org.junit.jupiter.api.Tag;
26+
27+
@Target({TYPE, METHOD})
28+
@Retention(RUNTIME)
29+
@Tag("cliNativeNpm")
30+
public @interface CliNativeNpmTest {}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2021-2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of 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,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.tag;
17+
18+
import static java.lang.annotation.ElementType.METHOD;
19+
import static java.lang.annotation.ElementType.TYPE;
20+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
21+
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.Target;
24+
25+
import org.junit.jupiter.api.Tag;
26+
27+
@Target({TYPE, METHOD})
28+
@Retention(RUNTIME)
29+
@Tag("cliProcessNpm")
30+
public @interface CliProcessNpmTest {}

0 commit comments

Comments
 (0)