Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged

Dev #909

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
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ExcelExportSpec extends Specification implements OkHttpRestTrait, WithTrx
login()
}

void "test xlsx"() {
void "test xlsx org with id,name"() {
when:
Response resp = get("${path}?q=*&format=xlsx")

Expand All @@ -32,7 +32,23 @@ class ExcelExportSpec extends Specification implements OkHttpRestTrait, WithTrx

then: "column name should have been resolved from grid col model"
headers
//flex.text1 does not have a label, so it would have used getNaturalTitle on name
headers.containsAll(['Num', 'Name', 'Type', 'TotalDue', 'Flex Text1', "Text 2"])
}

void "test xlsx contact with name and label"() {
when:
Response resp = get("/api/rally/contact?q=*&format=xlsx")

then:
resp.code() == HttpStatus.OK.value()

when: "verify excel file"
XSSFWorkbook workbook = new XSSFWorkbook(resp.body().byteStream())
List<String> headers = getHeader(workbook)

then: "column name should have been resolved from grid col model"
headers
//flex.text1 has name and label
headers.containsAll(['Name', 'Email', 'Email Type', 'Phone Type', "Is Primary"])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package yakworks.rest

import gorm.tools.transaction.WithTrx
import grails.gorm.transactions.Rollback
import grails.gorm.transactions.Transactional
import okhttp3.Request
import okhttp3.RequestBody
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.springframework.http.HttpStatus

import spock.lang.Ignore
import spock.lang.IgnoreRest
import yakworks.rally.orgs.model.Location
import yakworks.rest.client.OkAuth
import yakworks.rest.client.OkHttpRestTrait
import grails.testing.mixin.integration.Integration
Expand Down Expand Up @@ -362,17 +364,27 @@ class OrgRestApiSpec extends Specification implements OkHttpRestTrait, WithTrx {
body.errors[0].message == 'must not be null'
}

@Transactional
void "testing put"() {
when:
Response resp = put(path, [name: "9Galt"], 67)
setup:
int countBefore = Location.count()
Location existing = Org.get(67).location

when:
Response resp = put(path, [name: "9Galt", location:[city:"test"], locations:[[:]]], 67)
Map body = bodyToMap(resp)
Location updated = Org.get(67).location
int countAfter = Location.count()

then:
resp.code() == HttpStatus.OK.value()
body.id
body.name == '9Galt'

and:
countBefore == countAfter
existing.id == updated.id
updated.city == "test"
}

void "test post with tags"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package yakworks.security
import grails.testing.mixin.integration.Integration
import okhttp3.Request
import okhttp3.Response
import spock.lang.Ignore
import spock.lang.Specification

import yakworks.rest.client.OkHttpRestTrait

/**
* test the legacy login with post username and password to login endpoint.
*/
@Ignore
@Integration
class JsonUsernamePasswordLoginSpec extends Specification implements OkHttpRestTrait {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.springframework.http.HttpStatus
import org.springframework.security.oauth2.core.OAuth2AccessToken

import grails.testing.mixin.integration.Integration
import spock.lang.Ignore
import spock.lang.Specification

import yakworks.rest.client.OkAuth
Expand All @@ -16,6 +17,7 @@ import yakworks.security.spring.token.store.TokenStore

import java.time.ZoneId

@Ignore
@Integration
class OpaqueRestApiSpec extends Specification implements OkHttpRestTrait {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ class RallyApiSpringConfig {

http.oauth2Login(withDefaults())

//tokenLegacy for using username/password json in api/login, forwards to api/tokenLegacy which saves random string in db as token
DefaultSecurityConfiguration.addJsonAuthenticationFilter(http, tokenStore)
// Legacy tokenLegacy for using username/password json in api/login, forwards to api/tokenLegacy which saves random string in db as token
// DefaultSecurityConfiguration.addJsonAuthenticationFilter(http, tokenStore)

//enables jwt and oauth
DefaultSecurityConfiguration.applyOauthJwt(http)

Expand Down
14 changes: 7 additions & 7 deletions examples/rally-api/src/main/resources/restapi/rally/org.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ api:
bulkError: ['num', 'name']
gridOptions:
colModel:
- {name: id, width: 10, hidden: true }
- {name: num, label: Num, width: 40, formatter: editActionLink}
- {name: name, label: Name, width: 80}
- {name: type.name, label: Type, width: 40}
- {name: calc.totalDue, label: TotalDue, width: 40, formatter: currency}
- {name: flex.text1, width: 40} #A column without label, should not fail, and would use name as header, both in grid and in xslx export
- {id: flex.text2, label: Text 2} #use id instead of name, excel builder should work with either of them
- {id: id, width: 10, hidden: true }
- {id: num, name: Num, width: 40, formatter: editActionLink}
- {id: name, name: Name, width: 80}
- {id: type.name, name: Type, width: 40}
- {id: calc.totalDue, name: TotalDue, width: 40, formatter: currency}
- {id: flex.text1, width: 40} #A column without label, should not fail, and would use name as header, both in grid and in xslx export
- {id: flex.text2, name: Text 2} #use id instead of name, excel builder should work with either of them
# shrinkToFit: true
contextMenu: true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,18 @@ class ExcelBuilderSupport {
if(colModel){
colModel.each {
if(!it.hidden) {
//colModel need to specify at least field name or id, name/id is the name of domain field,
//label is optional, if provided it would be used for xls header

String columnName = it['name'] ?: it['id']
//if it contains id, its the new grid config, where id=field name and name=label
String columnName, label
if(it['id']) {
columnName = it['id'] as String
label = it['name'] as String
} else {
//old jquery jqGrid config new grid, where name=fieldname and label=label
columnName = it['name'] as String
label = it['label'] as String
}
Validate.notEmpty(columnName, "name or id is required for columns in gridOptions.colMode")
colMap[columnName] = it.label as String
colMap[columnName] = label as String
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,14 @@ class MangoTidyMap {
toMangoOperator(val as Map, result[key] as Map)
}
else {
if (key.toString().startsWith('$')) {
//if its a like then replace star
if ((key.toString() == '$ilike' || key.toString() == '$like') && val instanceof String ){
result[key] = val.endsWith("*") ? val.replace('*', '%') : val
}
else if (key.toString().startsWith('$')) {
result[key] = val
} //if we already have Mango method
}
//if we already have Mango method
else if (val instanceof List) {
List valAsList = val as List
// for handling case {customer: [{id:1}, {id:2}]}, transforms to {customer:{id:{'$in': [1,2]}}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,15 @@ trait GormRepo<D> implements ApiCrudRepo<D>, BulkableRepo<D>, ResolvableTypeProv

/**
* wraps get in a trx, usefull for testing. NOT a read only trx like read as that messes with dirty tracking
* Throws NotFoundExeption if null
* @param id the id to get
* @return the retrieved entity
*/
D getWithTrx(Serializable id) {
withTrx {
return (D)gormStaticApi().get(id)
var instance = (D)gormStaticApi().get(id)
RepoUtil.checkFound(instance, id, getEntityClass().simpleName)
return instance
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,74 @@ class MangoTidyMapSpec extends Specification {
]
}

void "test like with star *"() {
when: 'its already in $ilike'
def mmap = tidy([
name: ['$ilike': "Name*"]
])

then: 'it gets replaced with %'
mmap == [name: ['$ilike': "Name%"]]

when: 'its already in $like'
mmap = tidy([
name: ['$like': "*ame*"]
])

then: 'it gets replaced with %'
mmap == [name: ['$like': "%ame%"]]

when:
mmap = tidy([
'foo.name': "Name*"
])

then:
mmap == [foo: [name: ['$ilike': "Name%"]]]

when:
mmap = tidy(
[foo:
[name: "Name*"]
])

then:
mmap == [foo: [name: ['$ilike': "Name%"]]]

when: "wrapped in a not"
mmap = tidy([
'$not':[
'foo':[
name: "Name*"
]
]
])

then: "converts it to a list"
mmap == [
'$not': [ //list
[foo: [name: ['$ilike': "Name%"]]]
]
]

when: "wrapped in a not shortcut"
mmap = tidy([
'$not':[
'foo.name': "Name*",
'buzz.boo': "bar*"
]
])

then: "converts it to a list of maps"
mmap == [
'$not': [
[foo: [name: ['$ilike': "Name%"]]],
[buzz: [boo: ['$ilike': 'bar%']]]
]
]
}


void "test not simple"() {
when: 'the $not is a simple map'
def mmap = tidy([
Expand Down Expand Up @@ -452,11 +520,11 @@ class MangoTidyMapSpec extends Specification {

when:
mmap = tidy([
'foo.name.$like': "Name"
'foo.name.$like': "Name*"
])

then:
mmap == [foo: [name: ['$like': "Name"]]]
mmap == [foo: [name: ['$like': "Name%"]]]

when:
mmap = tidy([
Expand Down Expand Up @@ -535,7 +603,7 @@ class MangoTidyMapSpec extends Specification {
mmap = tidy([
'$not':[
'$exists': crit,
'name': 'org4%'
'name': 'org4*'
]
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,61 @@ class OrgRepoTests extends Specification implements DomainIntTest {
org.location.city == 'Denver'
}

void "update existing primary location"() {
setup:
Org org = Org.get(11)

expect:
org
org.location

int countBefore = Location.count()

when:
Location existingLocation = org.location
Map data = [
id: org.id,
location: [
city: 'Denver',
street1: '1st'
],
]
org = orgRepo.update(data)
flush()
int countAfter = Location.count()

then: "existing primary location should have been updated"
noExceptionThrown()
org.location
org.location.id == existingLocation.id
org.location.city == "Denver"
org.location.street1 == "1st"

and: "no new locations added"
countBefore == countAfter
}

void "should not create empty locations"() {
setup:
Org org = Org.get(11)
int countBefore = Location.count()

when:
Map data = [
id: org.id,
locations:[
[:]
]
]
orgRepo.update(data)
flushAndClear()
int countAfter = Location.count()

then: "no new location should be added"
noExceptionThrown()
countBefore == countAfter
}

void "test insert with orgmembers"() {
given:
OrgDimensionTesting.setDimensions(['Branch', 'Division', 'Business'])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ class UserInfoExt {
@NullCheck
static Org getOrg(UserInfo userInfo){
Validate.notNull(userInfo.orgId, "userInfo.orgId is null for user:[id:${userInfo.id}, username: ${userInfo.username}]")
return Org.repo.getWithTrx(userInfo.orgId)
try {
return Org.repo.getWithTrx(userInfo.orgId)
} catch(e) {
return null
}

}

static boolean isCustomer(UserInfo self){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ abstract class AbstractOrgRepo extends LongIdGormRepo<Org> {
*/
void persistToManyWithOrgId(Org org, GormRepo assocRepo, List<Map> assocList){
if(!assocList) return
//remove, if there are any empty maps.
assocList = assocList.findAll { Map it -> it.size() > 0}
assocList.each { it['orgId'] = org.getId()}
assocRepo.createOrUpdate(assocList)
}
Expand Down Expand Up @@ -228,6 +230,13 @@ abstract class AbstractOrgRepo extends LongIdGormRepo<Org> {
if(!data) return
//make sure params has org key
data.orgId = org.getId()

//if org already has a location, then set the existing location's id if not provided
//so that upsert will update existing location and not try to create a new one.
if(org.location && !data['id']) {
data['id'] = org.location.id
}

// if it had an op of remove then will return null and this set primary location to null
org.location = locationRepo.upsert(data).entity
return org.location
Expand Down