Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests to Language class #10

Merged
merged 1 commit into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ dashboard.
### Gateway Registration

```bash
export GATEWAY_PUBLIC_IP=52.53.186.26
export GATEWAY_PUBLIC_IP=<gateway IP>

# vocabulary paged & count
curl -v -i -s -k -X POST https://api.paion-data.dev:8444/services \
Expand Down
87 changes: 87 additions & 0 deletions src/test/groovy/org/qubitpi/wilhelm/LanguageSpec.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Jiaqi Liu
*
* 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 org.qubitpi.wilhelm

import spock.lang.Specification

import java.util.stream.Collectors

class LanguageSpec extends Specification {

def 'There are 3 valid languages'() {
expect:
Language.values().size() == 3
}

def "Only certain languages are supported"() {
given: "all restricted languages"
List<String> allValidDatabaseNames = ["German", "Ancient Greek", "Latin"]
List<String> allValidPathNames = ["german", "ancientGreek", "latin"]

expect: "no other database name is allowed"
allValidDatabaseNames.containsAll(
Arrays.stream(Language.values()).map {it -> it.databaseName}.collect(Collectors.toList())
)

and: "no other API path name is allowed"
allValidPathNames.containsAll(Arrays.stream(Language.values()).map {it -> it.pathName}.collect(Collectors.toList()))
}

def "'#databaseName' can be converted to object"() {
when: "a supported database name is being converted to a Language object"
Language.ofDatabaseName(databaseName)

then: "no error occurs"
noExceptionThrown()

where:
_ | databaseName
_ | "German"
_ | "Ancient Greek"
_ | "Latin"
}

def "'#pathName' can be converted to object"() {
when: "a supported API language name is being converted to a Language object"
Language.ofClientValue(pathName)

then: "no error occurs"
noExceptionThrown()

where:
_ | pathName
_ | "german"
_ | "ancientGreek"
_ | "latin"
}

@SuppressWarnings('GroovyAccessibility')
def "Invalid language cannot construct the object"() {
when: "invalid database name is used to construct the object"
Language.valueOf("foo", (language) -> language.getDatabaseName())

then: "error occurs"
Exception exception = thrown(IllegalArgumentException)
exception.message == "'foo' is not a recognized language. Acceptable ones are German, Ancient Greek, Latin"

when: "invalid API path name is used to construct the object"
Language.valueOf("foo", (language) -> language.getPathName())

then: "error occurs"
exception = thrown(IllegalArgumentException)
exception.message == "'foo' is not a recognized language. Acceptable ones are german, ancientGreek, latin"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Copyright Jiaqi Liu
*
* 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 org.qubitpi.wilhelm.web.filters

import jakarta.ws.rs.container.ContainerRequestContext
import jakarta.ws.rs.container.ContainerResponseContext
import jakarta.ws.rs.core.MultivaluedHashMap
import jakarta.ws.rs.core.MultivaluedMap
import jakarta.ws.rs.core.Response
import spock.lang.Specification
import spock.lang.Unroll

class LanguageCheckFilterSpec extends Specification {

def "When a request #beingPreflight preflight, request #beingAborted aborted"() {
setup: "a request is being configure for being preflight or not"
ContainerRequestContext request = Mock(ContainerRequestContext)

if (isPreflight) {
request.getHeaderString("Origin") >> "some origin"
request.getMethod() >> "OPTIONS"
} else {
request.getHeaderString("Origin") >> null
request.getMethod() >> "POST"
}

when: "the request is pre-matched by CORS filter"
new CorsFilter().filter(request)

then: "preflight request is bounced back and non-preflight request is accepted"
(isPreflight ? 1 : 0) * request.abortWith(_ as Response)

where:
_ | isPreflight
_ | true
_ | false

beingPreflight = isPreflight ? "is" : "is not"
beingAborted = isPreflight ? "is" : "is not"
}

@Unroll
def "When a request #beingCrossOrigin cross-origin and #beingPreflight preflight, response headers are #expectedResponseHeaders"() {
setup: "a request is being configure for being cross-origin/preflight or not"
ContainerRequestContext request = Mock(ContainerRequestContext)
ContainerResponseContext response = Mock(ContainerResponseContext)

if (isCrossOrigin) {
request.getHeaderString("Origin") >>> ["some origin"]
} else {
request.getHeaderString("Origin") >>> [null]
}

if (isPreflight) {
request.getHeaderString("Origin") >>> ["some origin"]
request.getMethod() >> "OPTIONS"
} else {
request.getHeaderString("Origin") >>> [null]
request.getMethod() >> "POST"
}

MultivaluedMap headers = new MultivaluedHashMap()
response.getHeaders() >>> [headers, headers, headers, headers]

when: "a response is being processed by CORS filter"
new CorsFilter().filter(request, response)

then: "the response header gets populated based on cross-origin/preflight nature of the configured request"
response.getHeaders() == expectedResponseHeaders

where:
isCrossOrigin | isPreflight || expectedResponseHeaders
false | false || [:]
false | true || [:]
true | false || accessControlAllowOrigin()
true | true || accessControlAllowHeaders() << accessControlAllowCredentials() << accessControlAllowMethods() << accessControlAllowOrigin()

beingCrossOrigin = isCrossOrigin ? "is" : "is not"
beingPreflight = isPreflight ? "is" : "is not"
}

@SuppressWarnings('GroovyAccessibility')
def "When a request #contains 'Origin' header, it #is a cross origin request"() {
given:
ContainerRequestContext request = Mock(ContainerRequestContext)

if (isCorssOrigin) {
request.getHeaderString("Origin") >> "some origin"
} else {
request.getHeaderString("Origin") >> null
}

expect:
CorsFilter.isCrossOriginRequest(request) == isCorssOrigin

where:
_ || isCorssOrigin
_ || true
_ || false

contains = isCorssOrigin ? "contains" : "does not contain"
is = isCorssOrigin ? "is" : "is not"
}

@SuppressWarnings('GroovyAccessibility')
def "When a request #containsOrigin 'Origin' header and method #isOptions 'OPTIONS', it #is a preflight request"() {
given:
ContainerRequestContext request = Mock(ContainerRequestContext)

if (isCorssOrigin) {
request.getHeaderString("Origin") >> "some origin"
} else {
request.getHeaderString("Origin") >> null
}

if (methodIsOptions) {
request.getMethod() >> "OPTIONS"
} else {
request.getMethod() >> "POST"
}

expect:
CorsFilter.isPreflightRequest(request) == isPreflight

where:
isCorssOrigin | methodIsOptions || isPreflight
false | false || false
false | true || false
true | false || false
true | true || true

containsOrigin = isCorssOrigin ? "contains" : "does not contain"
isOptions = isCorssOrigin ? "is" : "is not"
is = isPreflight ? "is" : "is not"
}

static def accessControlAllowHeaders() {
["Access-Control-Allow-Headers": ["CSRF-Token, X-Requested-By, Authorization, Content-Type"]]
}

static def accessControlAllowCredentials() {
["Access-Control-Allow-Credentials": ["true"]]
}

static def accessControlAllowMethods() {
["Access-Control-Allow-Methods": ["GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH"]]
}

static def accessControlAllowOrigin() {
["Access-Control-Allow-Origin": ["*"]]
}
}
Loading