feat(soft-assertions): Implement soft assertions for playwright-java (#1361)

This commit is contained in:
uchagani 2023-08-28 15:41:44 -04:00 committed by GitHub
parent fa75e29fcf
commit 86f929aaf0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 986 additions and 13 deletions

View File

@ -73,5 +73,9 @@
<groupId>com.microsoft.playwright</groupId>
<artifactId>driver-bundle</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) Microsoft Corporation.
*
* 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.microsoft.playwright.assertions;
import com.microsoft.playwright.impl.SoftAssertionsImpl;
import com.microsoft.playwright.APIResponse;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
/**
* The {@code SoftAssertions} class provides assertion methods that can be used to make multiple assertions without failing
* the test immediately.
* <pre>{@code
* ...
* import com.microsoft.playwright.assertions.SoftAssertions;
*
* public class TestPage {
* ...
* @Test
* void hasUrlTextPass() {
* SoftAssertions softly = SoftAssertions.create();
* page.getByText("Sign in").click();
* softly.assertThat(page).hasURL(Pattern.compile(".*\/login"));
* softly.assertAll();
* }
* }
* }</pre>
*/
public interface SoftAssertions {
/**
* Creates a {@code SoftAssertions} object.
*
* <p> **Usage**
* <pre>{@code
* SoftAssertions softly = SoftAssertions.create();
* }</pre>
*
* @since v1.38
*/
static SoftAssertions create() {
return new SoftAssertionsImpl();
}
/**
* Creates a {@code LocatorAssertions} object for the given {@code Locator}.
*
* <p> **Usage**
* <pre>{@code
* SoftAssertions softly = SoftAssertions.create();
* ...
* softly.assertThat(locator).isVisible();
* }</pre>
*
* @param locator {@code Locator} object to use for assertions.
* @since v1.38
*/
LocatorAssertions assertThat(Locator locator);
/**
* Creates a {@code PageAssertions} object for the given {@code Page}.
*
* <p> **Usage**
* <pre>{@code
* SoftAssertions softly = SoftAssertions.create();
* ...
* softly.assertThat(page).hasTitle("News");
* }</pre>
*
* @param page {@code Page} object to use for assertions.
* @since v1.38
*/
PageAssertions assertThat(Page page);
/**
* Creates a {@code APIResponseAssertions} object for the given {@code APIResponse}.
*
* <p> **Usage**
* <pre>{@code
* SoftAssertions softly = SoftAssertions.create();
* ...
* softly.assertThat(response).isOK();
* }</pre>
*
* @param response {@code APIResponse} object to use for assertions.
* @since v1.38
*/
APIResponseAssertions assertThat(APIResponse response);
/**
* Runs all the assertions have been executed for this {@code SoftAssertions} object. If any assertions fail, this method
* throws an AssertionFailedError with the details of all the failed assertions.
*
* <p> **Usage**
* <pre>{@code
* SoftAssertions softly = SoftAssertions.create();
* ...
* softly.assertAll();
* }</pre>
*
* @since v1.38
*/
void assertAll();
}

View File

@ -37,7 +37,7 @@ public class APIResponseAssertionsImpl implements APIResponseAssertions {
}
@Override
public APIResponseAssertions not() {
public APIResponseAssertionsImpl not() {
return new APIResponseAssertionsImpl(actual, !isNot);
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) Microsoft Corporation.
*
* 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.microsoft.playwright.impl;
import com.microsoft.playwright.APIResponse;
import com.microsoft.playwright.assertions.APIResponseAssertions;
import java.util.List;
public class APIResponseAssertionsImplProxy extends SoftAssertionsBase implements APIResponseAssertions {
private final APIResponseAssertionsImpl apiResponseAssertionsImpl;
APIResponseAssertionsImplProxy(APIResponse response, List<Throwable> results) {
this(results, new APIResponseAssertionsImpl(response));
}
private APIResponseAssertionsImplProxy(List<Throwable> results, APIResponseAssertionsImpl apiResponseAssertionsImpl) {
super(results);
this.apiResponseAssertionsImpl = apiResponseAssertionsImpl;
}
@Override
public APIResponseAssertions not() {
return new APIResponseAssertionsImplProxy(super.results, apiResponseAssertionsImpl.not());
}
@Override
public void isOK() {
assertAndCaptureResult(apiResponseAssertionsImpl::isOK);
}
}

View File

@ -353,7 +353,7 @@ public class LocatorAssertionsImpl extends AssertionsBase implements LocatorAsse
}
@Override
public LocatorAssertions not() {
public LocatorAssertionsImpl not() {
return new LocatorAssertionsImpl(actualLocator, !isNot);
}

View File

@ -0,0 +1,195 @@
package com.microsoft.playwright.impl;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.assertions.LocatorAssertions;
import java.util.List;
import java.util.regex.Pattern;
public class LocatorAssertionsImplProxy extends SoftAssertionsBase implements LocatorAssertions {
private final LocatorAssertionsImpl locatorAssertionsImpl;
LocatorAssertionsImplProxy(Locator locator, List<Throwable> results) {
this(results, new LocatorAssertionsImpl(locator));
}
private LocatorAssertionsImplProxy(List<Throwable> results, LocatorAssertionsImpl locatorAssertionsImpl) {
super(results);
this.locatorAssertionsImpl = locatorAssertionsImpl;
}
@Override
public LocatorAssertions not() {
return new LocatorAssertionsImplProxy(super.results, locatorAssertionsImpl.not());
}
@Override
public void isAttached(IsAttachedOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isAttached(options));
}
@Override
public void isChecked(IsCheckedOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isChecked(options));
}
@Override
public void isDisabled(IsDisabledOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isDisabled(options));
}
@Override
public void isEditable(IsEditableOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isEditable(options));
}
@Override
public void isEmpty(IsEmptyOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isEmpty(options));
}
@Override
public void isEnabled(IsEnabledOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isEnabled(options));
}
@Override
public void isFocused(IsFocusedOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isFocused(options));
}
@Override
public void isHidden(IsHiddenOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isHidden(options));
}
@Override
public void isInViewport(IsInViewportOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isInViewport(options));
}
@Override
public void isVisible(IsVisibleOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.isVisible(options));
}
@Override
public void containsText(String expected, ContainsTextOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.containsText(expected, options));
}
@Override
public void containsText(Pattern expected, ContainsTextOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.containsText(expected, options));
}
@Override
public void containsText(String[] expected, ContainsTextOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.containsText(expected, options));
}
@Override
public void containsText(Pattern[] expected, ContainsTextOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.containsText(expected, options));
}
@Override
public void hasAttribute(String name, String value, HasAttributeOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasAttribute(name, value, options));
}
@Override
public void hasAttribute(String name, Pattern value, HasAttributeOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasAttribute(name, value, options));
}
@Override
public void hasClass(String expected, HasClassOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasClass(expected, options));
}
@Override
public void hasClass(Pattern expected, HasClassOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasClass(expected, options));
}
@Override
public void hasClass(String[] expected, HasClassOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasClass(expected, options));
}
@Override
public void hasClass(Pattern[] expected, HasClassOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasClass(expected, options));
}
@Override
public void hasCount(int count, HasCountOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasCount(count, options));
}
@Override
public void hasCSS(String name, String value, HasCSSOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasCSS(name, value, options));
}
@Override
public void hasCSS(String name, Pattern value, HasCSSOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasCSS(name, value, options));
}
@Override
public void hasId(String id, HasIdOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasId(id, options));
}
@Override
public void hasId(Pattern id, HasIdOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasId(id, options));
}
@Override
public void hasJSProperty(String name, Object value, HasJSPropertyOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasJSProperty(name, value, options));
}
@Override
public void hasText(String expected, HasTextOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasText(expected, options));
}
@Override
public void hasText(Pattern expected, HasTextOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasText(expected, options));
}
@Override
public void hasText(String[] expected, HasTextOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasText(expected, options));
}
@Override
public void hasText(Pattern[] expected, HasTextOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasText(expected, options));
}
@Override
public void hasValue(String value, HasValueOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasValue(value, options));
}
@Override
public void hasValue(Pattern value, HasValueOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasValue(value, options));
}
@Override
public void hasValues(String[] values, HasValuesOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasValues(values, options));
}
@Override
public void hasValues(Pattern[] values, HasValuesOptions options) {
assertAndCaptureResult(() -> locatorAssertionsImpl.hasValues(values, options));
}
}

View File

@ -67,7 +67,7 @@ public class PageAssertionsImpl extends AssertionsBase implements PageAssertions
}
@Override
public PageAssertions not() {
public PageAssertionsImpl not() {
return new PageAssertionsImpl(actualPage, !isNot);
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) Microsoft Corporation.
*
* 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.microsoft.playwright.impl;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.assertions.PageAssertions;
import java.util.List;
import java.util.regex.Pattern;
public class PageAssertionsImplProxy extends SoftAssertionsBase implements PageAssertions {
private final PageAssertionsImpl pageAssertionsImpl;
PageAssertionsImplProxy(Page page, List<Throwable> results) {
this(results, new PageAssertionsImpl(page));
}
private PageAssertionsImplProxy(List<Throwable> results, PageAssertionsImpl pageAssertionsImpl) {
super(results);
this.pageAssertionsImpl = pageAssertionsImpl;
}
@Override
public PageAssertions not() {
return new PageAssertionsImplProxy(super.results, pageAssertionsImpl.not());
}
@Override
public void hasTitle(String titleOrRegExp, HasTitleOptions options) {
assertAndCaptureResult(() -> pageAssertionsImpl.hasTitle(titleOrRegExp, options));
}
@Override
public void hasTitle(Pattern titleOrRegExp, HasTitleOptions options) {
assertAndCaptureResult(() -> pageAssertionsImpl.hasTitle(titleOrRegExp, options));
}
@Override
public void hasURL(String urlOrRegExp, HasURLOptions options) {
assertAndCaptureResult(() -> pageAssertionsImpl.hasURL(urlOrRegExp, options));
}
@Override
public void hasURL(Pattern urlOrRegExp, HasURLOptions options) {
assertAndCaptureResult(() -> pageAssertionsImpl.hasURL(urlOrRegExp, options));
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) Microsoft Corporation.
*
* 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.microsoft.playwright.impl;
import com.microsoft.playwright.PlaywrightException;
import org.opentest4j.AssertionFailedError;
import java.util.List;
class SoftAssertionsBase {
final List<Throwable> results;
SoftAssertionsBase(List<Throwable> results) {
this.results = results;
}
void assertAndCaptureResult(Runnable assertion) {
try {
assertion.run();
} catch (AssertionFailedError | PlaywrightException failure) {
results.add(failure);
}
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) Microsoft Corporation.
*
* 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.microsoft.playwright.impl;
import com.microsoft.playwright.APIResponse;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.assertions.APIResponseAssertions;
import com.microsoft.playwright.assertions.LocatorAssertions;
import com.microsoft.playwright.assertions.PageAssertions;
import com.microsoft.playwright.assertions.SoftAssertions;
import org.opentest4j.AssertionFailedError;
import java.util.ArrayList;
import java.util.List;
public class SoftAssertionsImpl implements SoftAssertions {
final List<Throwable> results;
public SoftAssertionsImpl() {
this.results = new ArrayList<>();
}
@Override
public LocatorAssertions assertThat(Locator locator) {
return new LocatorAssertionsImplProxy(locator, results);
}
@Override
public PageAssertions assertThat(Page page) {
return new PageAssertionsImplProxy(page, results);
}
@Override
public APIResponseAssertions assertThat(APIResponse response) {
return new APIResponseAssertionsImplProxy(response, results);
}
@Override
public void assertAll() {
if (!results.isEmpty()) {
throw new AssertionFailedError(getFormattedErrorMessage());
}
}
private String getFormattedErrorMessage() {
StringBuilder message = new StringBuilder();
message
.append(results.size())
.append(" assertion(s) failed:");
for (Throwable t : results) {
message.append("\n");
message.append("----------------------------------------\n");
message.append(t.getMessage());
}
return message.toString();
}
}

View File

@ -0,0 +1,47 @@
package com.microsoft.playwright;
import com.microsoft.playwright.assertions.APIResponseAssertions;
import com.microsoft.playwright.impl.APIResponseAssertionsImpl;
import com.microsoft.playwright.impl.APIResponseAssertionsImplProxy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static com.microsoft.playwright.Utils.createProxy;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.verify;
// The only thing we want to verify in these tests is that the correct method was called
@Tag("mockito")
@ExtendWith(MockitoExtension.class)
public class TestSoftAPIResponseAssertions {
@Mock
private APIResponseAssertionsImpl apiResponseAssertionsMock;
private APIResponseAssertionsImplProxy proxy;
@BeforeEach
void beforeEach() {
proxy = createProxy(APIResponseAssertionsImplProxy.class, apiResponseAssertionsMock);
}
@Test
void proxyImplementsAPIResponseAssertions() {
assertTrue(APIResponseAssertions.class.isAssignableFrom(proxy.getClass()));
}
@Test
void not() {
proxy.not();
verify(apiResponseAssertionsMock).not();
}
@Test
void isOK() {
assertDoesNotThrow(() -> proxy.isOK());
verify(apiResponseAssertionsMock).isOK();
}
}

View File

@ -0,0 +1,46 @@
package com.microsoft.playwright;
import com.microsoft.playwright.assertions.LocatorAssertions;
import com.microsoft.playwright.assertions.SoftAssertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;
import static org.junit.jupiter.api.Assertions.*;
public class TestSoftAssertions extends TestBase {
private SoftAssertions softly;
@BeforeEach
void beforeEach() {
softly = SoftAssertions.create();
}
@Test
void canMakeMultipleAssertionsWithoutFailingImmediately() {
page.setContent("<div id=node class='foo bar'>Text content</div>");
Locator locator = page.locator(".foo");
assertDoesNotThrow(() -> softly.assertThat(locator).hasText("Text content"));
assertDoesNotThrow(() -> softly.assertThat(locator).hasClass("foo bar"));
assertDoesNotThrow(() -> softly.assertThat(locator).hasId("node"));
softly.assertAll();
}
@Test
void failureMessageIncludesMessagesFromAllAssertions() {
page.setContent("<div id=node class='foo bar'>Text content</div>");
Locator locator = page.locator(".foo");
assertDoesNotThrow(() -> softly.assertThat(locator).hasText("some text", new LocatorAssertions.HasTextOptions().setTimeout(1000)));
assertDoesNotThrow(() -> softly.assertThat(locator).hasClass("abc", new LocatorAssertions.HasClassOptions().setTimeout(1000)));
assertDoesNotThrow(() -> softly.assertThat(locator).hasId("foo", new LocatorAssertions.HasIdOptions().setTimeout(1000)));
AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> softly.assertAll());
assertTrue(e.getMessage().contains("3 assertion(s) failed"));
assertTrue(e.getMessage().contains("Locator expected to have text: some text"));
assertTrue(e.getMessage().contains("Received: Text content"));
assertTrue(e.getMessage().contains("Locator expected to have class: abc"));
assertTrue(e.getMessage().contains("Received: foo bar"));
assertTrue(e.getMessage().contains("Locator expected to have ID: foo"));
assertTrue(e.getMessage().contains("Received: node"));
}
}

View File

@ -0,0 +1,250 @@
package com.microsoft.playwright;
import com.microsoft.playwright.assertions.LocatorAssertions;
import com.microsoft.playwright.impl.LocatorAssertionsImpl;
import com.microsoft.playwright.impl.LocatorAssertionsImplProxy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.regex.Pattern;
import static com.microsoft.playwright.Utils.createProxy;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.verify;
// The only thing we want to verify in these tests is that the correct method was called
@Tag("mockito")
@ExtendWith(MockitoExtension.class)
public class TestSoftLocatorAssertions {
@Mock
private LocatorAssertionsImpl locatorAssertionsMock;
private final static Pattern pattern = Pattern.compile("");
private final static Pattern[] patternArray = new Pattern[]{};
private final static String[] stringArray = new String[]{};
private LocatorAssertionsImplProxy proxy;
@BeforeEach
void beforeEach() {
proxy = createProxy(LocatorAssertionsImplProxy.class, locatorAssertionsMock);
}
@Test
void proxyImplementsLocatorAssertions() {
assertTrue(LocatorAssertions.class.isAssignableFrom(proxy.getClass()));
}
@Test
void not() {
proxy.not();
verify(locatorAssertionsMock).not();
}
@Test
void isAttached() {
assertDoesNotThrow(() -> proxy.isAttached(null));
verify(locatorAssertionsMock).isAttached(null);
}
@Test
void isChecked() {
assertDoesNotThrow(() -> proxy.isChecked(null));
verify(locatorAssertionsMock).isChecked(null);
}
@Test
void isDisabled() {
assertDoesNotThrow(() -> proxy.isDisabled(null));
verify(locatorAssertionsMock).isDisabled(null);
}
@Test
void isEditable() {
assertDoesNotThrow(() -> proxy.isEditable(null));
verify(locatorAssertionsMock).isEditable(null);
}
@Test
void isEmpty() {
assertDoesNotThrow(() -> proxy.isEmpty(null));
verify(locatorAssertionsMock).isEmpty(null);
}
@Test
void isEnabled() {
assertDoesNotThrow(() -> proxy.isEnabled(null));
verify(locatorAssertionsMock).isEnabled(null);
}
@Test
void isFocused() {
assertDoesNotThrow(() -> proxy.isFocused(null));
verify(locatorAssertionsMock).isFocused(null);
}
@Test
void isHidden() {
assertDoesNotThrow(() -> proxy.isHidden(null));
verify(locatorAssertionsMock).isHidden(null);
}
@Test
void isInViewPort() {
assertDoesNotThrow(() -> proxy.isInViewport(null));
verify(locatorAssertionsMock).isInViewport(null);
}
@Test
void isVisible() {
assertDoesNotThrow(() -> proxy.isVisible(null));
verify(locatorAssertionsMock).isVisible(null);
}
@Test
void containsTextString() {
assertDoesNotThrow(() -> proxy.containsText("", null));
verify(locatorAssertionsMock).containsText("", null);
}
@Test
void containsTextPattern() {
assertDoesNotThrow(() -> proxy.containsText(pattern, null));
verify(locatorAssertionsMock).containsText(pattern, null);
}
@Test
void containsTextStringArray() {
assertDoesNotThrow(() -> proxy.containsText(stringArray, null));
verify(locatorAssertionsMock).containsText(stringArray, null);
}
@Test
void containsTextPatternArray() {
assertDoesNotThrow(() -> proxy.containsText(patternArray, null));
verify(locatorAssertionsMock).containsText(patternArray, null);
}
@Test
void hasAttributeStringValue() {
assertDoesNotThrow(() -> proxy.hasAttribute("", "", null));
verify(locatorAssertionsMock).hasAttribute("", "", null);
}
@Test
void hasAttributePatternValue() {
assertDoesNotThrow(() -> proxy.hasAttribute("", pattern, null));
verify(locatorAssertionsMock).hasAttribute("", pattern, null);
}
@Test
void hasClassString() {
assertDoesNotThrow(() -> proxy.hasClass("", null));
verify(locatorAssertionsMock).hasClass("", null);
}
@Test
void hasClassPattern() {
assertDoesNotThrow(() -> proxy.hasClass(pattern, null));
verify(locatorAssertionsMock).hasClass(pattern, null);
}
@Test
void hasClassStringArray() {
assertDoesNotThrow(() -> proxy.hasClass(stringArray, null));
verify(locatorAssertionsMock).hasClass(stringArray, null);
}
@Test
void hasClassPatternArray() {
assertDoesNotThrow(() -> proxy.hasClass(patternArray, null));
verify(locatorAssertionsMock).hasClass(patternArray, null);
}
@Test
void hasCount() {
assertDoesNotThrow(() -> proxy.hasCount(0, null));
verify(locatorAssertionsMock).hasCount(0, null);
}
@Test
void hasCSSString() {
assertDoesNotThrow(() -> proxy.hasCSS("", "", null));
verify(locatorAssertionsMock).hasCSS("", "", null);
}
@Test
void hasCSSPattern() {
assertDoesNotThrow(() -> proxy.hasCSS("", pattern, null));
verify(locatorAssertionsMock).hasCSS("", pattern, null);
}
@Test
void hasIdString() {
assertDoesNotThrow(() -> proxy.hasId("", null));
verify(locatorAssertionsMock).hasId("", null);
}
@Test
void hasIdPattern() {
assertDoesNotThrow(() -> proxy.hasId(pattern, null));
verify(locatorAssertionsMock).hasId(pattern, null);
}
@Test
void hasJSProperty() {
assertDoesNotThrow(() -> proxy.hasJSProperty("", null, null));
verify(locatorAssertionsMock).hasJSProperty("", null, null);
}
@Test
void hasTextString() {
assertDoesNotThrow(() -> proxy.hasText("", null));
verify(locatorAssertionsMock).hasText("", null);
}
@Test
void hasTextPattern() {
assertDoesNotThrow(() -> proxy.hasText(pattern, null));
verify(locatorAssertionsMock).hasText(pattern, null);
}
@Test
void hasTextStringArray() {
assertDoesNotThrow(() -> proxy.hasText(stringArray, null));
verify(locatorAssertionsMock).hasText(stringArray, null);
}
@Test
void hasTextPatternArray() {
assertDoesNotThrow(() -> proxy.hasText(patternArray, null));
verify(locatorAssertionsMock).hasText(patternArray, null);
}
@Test
void hasValueString() {
assertDoesNotThrow(() -> proxy.hasValue("", null));
verify(locatorAssertionsMock).hasValue("", null);
}
@Test
void hasValuePattern() {
assertDoesNotThrow(() -> proxy.hasValue(pattern, null));
verify(locatorAssertionsMock).hasValue(pattern, null);
}
@Test
void hasValuesStringArray() {
assertDoesNotThrow(() -> proxy.hasValues(stringArray, null));
verify(locatorAssertionsMock).hasValues(stringArray, null);
}
@Test
void hasValuesPatternArray() {
assertDoesNotThrow(() -> proxy.hasValues(patternArray, null));
verify(locatorAssertionsMock).hasValues(patternArray, null);
}
}

View File

@ -0,0 +1,68 @@
package com.microsoft.playwright;
import com.microsoft.playwright.assertions.PageAssertions;
import com.microsoft.playwright.impl.PageAssertionsImpl;
import com.microsoft.playwright.impl.PageAssertionsImplProxy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.regex.Pattern;
import static com.microsoft.playwright.Utils.createProxy;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.verify;
// The only thing we want to verify in these tests is that the correct method was called
@Tag("mockito")
@ExtendWith(MockitoExtension.class)
public class TestSoftPageAssertions {
@Mock
private PageAssertionsImpl pageAssertionsMock;
private PageAssertionsImplProxy proxy;
private final static Pattern pattern = Pattern.compile("");
@BeforeEach
void beforeEach() {
proxy = createProxy(PageAssertionsImplProxy.class, pageAssertionsMock);
}
@Test
void proxyImplementsPageAssertions() {
assertTrue(PageAssertions.class.isAssignableFrom(proxy.getClass()));
}
@Test
void not() {
proxy.not();
verify(pageAssertionsMock).not();
}
@Test
void hasTitleString() {
assertDoesNotThrow(() -> proxy.hasTitle("", null));
verify(pageAssertionsMock).hasTitle("", null);
}
@Test
void hasTitlePattern() {
assertDoesNotThrow(() -> proxy.hasTitle(pattern, null));
verify(pageAssertionsMock).hasTitle(pattern, null);
}
@Test
void hasURLString() {
assertDoesNotThrow(() -> proxy.hasURL("", null));
verify(pageAssertionsMock).hasURL("", null);
}
@Test
void hasURLPattern() {
assertDoesNotThrow(() -> proxy.hasURL(pattern, null));
verify(pageAssertionsMock).hasURL(pattern, null);
}
}

View File

@ -21,18 +21,18 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.ServerSocket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mockingDetails;
class Utils {
private static final AtomicInteger nextUnusedPort = new AtomicInteger(9000);
@ -214,4 +214,14 @@ class Utils {
static String generateDifferentOriginPort(final Server server){
return server.PREFIX.replace(String.valueOf(server.PORT), String.valueOf(server.PORT+1));
}
static <T> T createProxy(Class<?> proxyToCreate, Object underlyingObject) {
try {
Constructor<?> constructor = proxyToCreate.getDeclaredConstructor(List.class, mockingDetails(underlyingObject).getMockCreationSettings().getTypeToMock());
constructor.setAccessible(true);
return (T) proxyToCreate.cast(constructor.newInstance(new ArrayList<>(), underlyingObject));
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException("Unable to create proxy", e);
}
}
}

View File

@ -49,6 +49,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<websocket.version>1.5.1</websocket.version>
<opentest4j.version>1.2.0</opentest4j.version>
<mockito.version>4.11.0</mockito.version>
</properties>
<dependencyManagement>
@ -85,6 +86,12 @@
<version>${websocket.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -688,6 +688,13 @@ class Method extends Element {
output.add("");
return;
}
if ("SoftAssertions.create".equals(jsonPath)) {
writeJavadoc(params, output, offset);
output.add(offset + "static SoftAssertions create() {");
output.add(offset + " return new SoftAssertionsImpl();");
output.add(offset + "}");
return;
}
int numOverloads = 1;
for (int i = 0; i < params.size(); i++) {
if (params.get(i).type.isTypeUnion()) {
@ -989,6 +996,11 @@ class Interface extends TypeDefinition {
output.add("import com.microsoft.playwright.impl.LocatorAssertionsImpl;");
output.add("import com.microsoft.playwright.impl.PageAssertionsImpl;");
}
if ("SoftAssertions".equals(jsonName)) {
output.add("import com.microsoft.playwright.APIResponse;");
output.add("import com.microsoft.playwright.Locator;");
output.add("import com.microsoft.playwright.Page;");
}
output.add("");
List<String> superInterfaces = new ArrayList<>();
@ -1156,18 +1168,13 @@ public class ApiGenerator {
File assertionsDir = new File(cwd,"playwright/src/main/java/com/microsoft/playwright/assertions");
System.out.println("Writing assertion files to: " + dir.getCanonicalPath());
generate(api, assertionsDir, "com.microsoft.playwright.assertions", isAssertion().and(isSoftAssertion().negate()));
generate(api, assertionsDir, "com.microsoft.playwright.assertions", isAssertion());
}
private static Predicate<String> isAssertion() {
return className -> className.toLowerCase().contains("assert");
}
// TODO: Remove this predicate once SoftAssertions are implemented.
private static Predicate<String> isSoftAssertion() {
return className -> className.contains("SoftAssertions");
}
private void generate(JsonArray api, File dir, String packageName, Predicate<String> classFilter) throws IOException {
Map<String, TypeDefinition> topLevelTypes = new HashMap<>();
for (JsonElement entry: api) {

View File

@ -13,6 +13,7 @@
<junit.version>5.7.0</junit.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<websocket.version>1.5.1</websocket.version>
<mockito.version>4.11.0</mockito.version>
</properties>
<dependencies>
<dependency>
@ -43,6 +44,12 @@
<artifactId>Java-WebSocket</artifactId>
<version>${websocket.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>