/* * Copyright 2017-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.js; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.in; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.model.Pair; import com.facebook.buck.model.UserFlavor; import com.facebook.buck.parser.NoSuchBuildTargetException; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.DefaultBuildTargetSourcePath; import com.facebook.buck.rules.FakeSourcePath; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.util.RichStream; import com.google.common.collect.ImmutableSortedSet; import org.junit.Before; import org.junit.Test; public class JsLibraryDescriptionTest { private static final String targetDirectory = "arbitrary/path"; private JsTestScenario.Builder scenarioBuilder; private BuildTarget target; @Before public void setUp() throws NoSuchBuildTargetException { scenarioBuilder = JsTestScenario.builder(); target = BuildTargetFactory.newInstance(String.format("//%s:target", targetDirectory)); } @Test public void subBasePathForSourceFiles() throws NoSuchBuildTargetException { final String basePath = "base/path"; final String filePath = String.format("%s/sub/file.js", targetDirectory); final JsTestScenario scenario = buildScenario(basePath, new FakeSourcePath(filePath)); assertEquals( "arbitrary/path/base/path/sub/file.js", findFileRule(scenario.resolver).getVirtualPath().get()); } @Test public void relativeBasePathForSourceFiles() throws NoSuchBuildTargetException { final String basePath = "../base/path"; final String filePath = String.format("%s/sub/file.js", targetDirectory); final JsTestScenario scenario = buildScenario(basePath, new FakeSourcePath(filePath)); assertEquals( "arbitrary/base/path/sub/file.js", findFileRule(scenario.resolver).getVirtualPath().get()); } @Test public void basePathReplacesBuildTargetSourcePath() throws NoSuchBuildTargetException { final String basePath = "base/path.js"; final BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); scenarioBuilder.arbitraryRule(target); final JsTestScenario scenario = buildScenario(basePath, new DefaultBuildTargetSourcePath(target)); assertEquals( "arbitrary/path/base/path.js", findFileRule(scenario.resolver).getVirtualPath().get()); } @Test public void relativeBasePathReplacesBuildTargetSourcePath() throws NoSuchBuildTargetException { final String basePath = "../path.js"; final BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); scenarioBuilder.arbitraryRule(target); final JsTestScenario scenario = buildScenario(basePath, new DefaultBuildTargetSourcePath(target)); assertEquals("arbitrary/path.js", findFileRule(scenario.resolver).getVirtualPath().get()); } @Test public void buildTargetWithSubpathPair() throws NoSuchBuildTargetException { final String basePath = "."; final BuildTarget target = BuildTargetFactory.newInstance("//:node_modules"); scenarioBuilder.arbitraryRule(target); final JsTestScenario scenario = buildScenario( basePath, new Pair<>(new DefaultBuildTargetSourcePath(target), "node_modules/left-pad/index.js")); assertEquals( "arbitrary/path/node_modules/left-pad/index.js", findFileRule(scenario.resolver).getVirtualPath().get()); } @Test public void propagatesReleaseAndPlatformFlavors() throws NoSuchBuildTargetException { ImmutableSortedSet<UserFlavor> flavors = ImmutableSortedSet.of(JsFlavors.IOS, JsFlavors.RELEASE); BuildTarget withFlavors = this.target.withFlavors(flavors); JsTestScenario scenario = scenarioBuilder .library(withFlavors, new FakeSourcePath("apples"), new FakeSourcePath("pears")) .build(); RichStream.from(scenario.resolver.getRule(withFlavors).getBuildDeps()) .filter(JsFile.class) .map(JsFile::getBuildTarget) .forEach( target -> assertThat( String.format( "JsFile dependency `%s` of JsLibrary `%s` must have flavors `%s`", target, withFlavors, flavors), flavors, everyItem(in(target.getFlavors())))); } @Test public void doesNotpropagatePlatformFlavorsWithoutRelease() throws NoSuchBuildTargetException { UserFlavor platformFlavor = JsFlavors.ANDROID; BuildTarget withPlatformFlavor = target.withFlavors(platformFlavor); JsTestScenario scenario = scenarioBuilder .library(withPlatformFlavor, new FakeSourcePath("apples"), new FakeSourcePath("pears")) .build(); long numFileDeps = RichStream.from(scenario.resolver.getRule(withPlatformFlavor).getBuildDeps()) .filter(JsFile.class) .map(JsFile::getBuildTarget) .peek( fileTarget -> assertFalse( String.format( "JsFile dependency `%s` of JsLibrary `%s` must not have flavor `%s`", fileTarget, withPlatformFlavor, platformFlavor), fileTarget.getFlavors().contains(platformFlavor))) .count(); assertNotEquals(0, numFileDeps); } private JsTestScenario buildScenario(String basePath, SourcePath source) throws NoSuchBuildTargetException { return scenarioBuilder.library(target, basePath, source).build(); } private JsTestScenario buildScenario(String basePath, Pair<SourcePath, String> source) throws NoSuchBuildTargetException { return scenarioBuilder.library(target, basePath, source).build(); } private JsFile.JsFileDev findFileRule(BuildRuleResolver resolver) { return RichStream.from(resolver.getRule(target).getBuildDeps()) .filter(JsFile.JsFileDev.class) .findFirst() .get(); } }