Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1164 lines (1114 sloc) 50.3 KB
<?xml version="1.0" encoding="UTF-8"?>
<restReplay>
<protoHostPort>http://localhost:${SELFTEST_PORT}</protoHostPort>
<testGroup ID="login" autoDeletePOSTS="false">
<test ID="token">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<exports>
<vars>
<var ID="exportedToken">${result.got("//data")}</var>
<var ID="status">${this.got("//status")}</var>
</vars>
</exports>
</test>
</testGroup>
<testGroup ID="selftestGroup" autoDeletePOSTS="false">
<comment>This is the main testGroup which self-tests the RestReplay installation, by hitting
the internal server launched for this test with
the CLI parameter <nobr><b>-selftest</b></nobr>.</comment>
<vars>
<var ID="SELFTEST_SERVER">http://localhost:${SELFTEST_PORT}</var>
</vars>
<test ID="simpleGET">
<uri>/tagonomy</uri>
</test>
<test ID="simpleGET_EmptyResponse">
<uri>/jsonCompare1</uri>
</test>
<test ID="token">
<comment>This token service always returns the same token, useful to simulate a real single-sign-on service.</comment>
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<exports>
<vars>
<var ID="data">${this.got("$..data")}</var>
</vars>
</exports>
</test>
<test ID="tokenWithXPath">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<exports>
<vars>
<var ID="datax">${this.got("//data")}</var>
</vars>
</exports>
</test>
<test ID="gotJson">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<exports>
<vars>
<var ID="JsonPathTest">${this.gotJson("$..data")}</var>
</vars>
</exports>
</test>
<test ID="gotJson_Warnings">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<exports>
<vars>
<var ID="JsonPathTestJsonPath">${this.got("$..data")}</var>
<var ID="JsonPathTestXPath">${this.got("//data")}</var>
<var ID="JsonPathTestEmpty">${this.got("")}</var>
</vars>
</exports>
</test>
<test ID="expectedCodes">
<expected>
<code range="3x"/>
<code range="1x"/>
<code range="2x"></code>
</expected>
<method>GET</method>
<uri>${SELFTEST_SERVER}/tagonomy?mock=true&amp;foo=${TOKEN_ID}</uri>
<vars>
<var ID="TOKEN_ID">${token.got("//status")}</var>
</vars>
</test>
<test ID="useMutator">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/content-mutator-test.json</filename>
<mutator type="ExcludeFields">
<expected>
<code range="200">*</code>
<code range="200-299">numOfDrafts</code>
<code range="400-499,500-599">book_id, course_id</code>
</expected>
</mutator>
<response>
<expected>
<dom>
<REMOVED range="0" />
<DIFFERENT range="0" />
</dom>
</expected>
<filename>_self_test/res/content-mutator-base.json</filename>
<validator lang="javascript"><![CDATA[
if (tools.notBlank(serviceResult.idFromMutator) ){
if (tools.notBlank(serviceResult.got("//"+serviceResult.idFromMutator))){
serviceResult.addError(" idFromMutator:"+serviceResult.idFromMutator);
} else {
"field was properly removed: "+serviceResult.idFromMutator;
}
}
]]></validator>
</response>
</test>
<test ID="useMutatorSkipParent">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/content-mutator-test.json</filename>
<mutator type="ExcludeFields" skipParent="true">
<expected>
<code range="200">*</code>
<code range="200-299">numOfDrafts</code>
<code range="400-499,500-599">book_id, course_id</code>
</expected>
</mutator>
</test>
<test ID="useLoop" loop="3" oldloop="${size(loopvars)}">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=application/json</uri>
<filename>_self_test/loop-dates.json</filename>
<vars>
<var ID="loopvars">${["10","18","21"]}</var>
<var ID="DAYS">${24*60*60*1000}</var>
<var ID="BASE_DATE">${tools.now()}</var>
<var ID="DUE_DATE_MILLIS">${BASE_DATE + loopvars[this.LoopIndex]*DAYS}</var>
<var ID="INSTRUCTOR_NOTE">Dr. L sez, assignment for ${DUE_DATE_MILLIS} label: ${this.testID}</var>
<var ID="TITLE">Due ${kit.dates.getMonthName(DUE_DATE_MILLIS)} ${kit.dates.getDayOfMonth(DUE_DATE_MILLIS)}</var>
</vars>
<response>
<expected>
<dom>
<REMOVED range="0" />
<DIFFERENT range="0" />
</dom>
</expected>
<filename>_self_test/res/loop-dates.json</filename>
</response>
</test>
<test ID="useToken">
<method>GET</method>
<uri>/tagonomy?mock=true&amp;name=useToken</uri>
<headers>
<header name="x-authorization">${token.got("//data")}</header>
<header name="x-method">${token.method}</header>
</headers>
</test>
<test ID="useTokenPOST">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-token-post.json</filename>
<vars>
<var ID="TOKEN">${token.got("//data")}</var>
<var ID="TOKENDATA">${token.got("//data")}</var>
<var ID="TESTIDLABEL_TEST">this.testIDLabel: ${this.testIDLabel} this.testID: ${this.testID}</var>
</vars>
</test>
<test ID="useTokenPUT">
<method>PUT</method>
<uri>/tagonomy?mock=true&amp;mutation=${this.mutation}</uri>
<filename>_self_test/content-mutator-test.json</filename>
<mutator type="ExcludeFields">
<expected>
<code range="4xx">*</code>
</expected>
</mutator>
</test>
<test ID="useTokenDELETE">
<method>DELETE</method>
<uri>/tagonomy?mock=true</uri>
</test>
<test ID="selftest501">
<expected>
<code range="501"/>
</expected>
<method>PUT</method>
<uri>/tagonomy?mock=501</uri>
<filename>_self_test/content-mutator-test.json</filename>
</test>
<test ID="scriptTest">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-mutator.json</filename>
<vars>
<var ID="TOKEN">FOOTOKEN</var>
</vars>
<exports>
<vars>
<comment>this stuff is JEXL, Java Expression Language: org.apache.commons.jexl2, and it is basically java, but has the var keyword.</comment>
<var ID="GregorianDate"><![CDATA[${
if (kit != null) {
var ts = kit.gregorian.timestampUTC();
kit.out.println('');
kit.out.println(' ==> Running test script, in selftest.xml:selftestGroup:scriptTest at '+ts);
kit.out.println('');
return 'zts:'+ts;
}
return "kit not defined in scriptTest";
}]]></var>
</vars>
</exports>
</test>
<test ID="useValidator">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-number-post.json</filename>
<vars>
<var ID="COUNT">3</var>
</vars>
<response>
<validator lang="javascript" filename="_self_test/res/selftest.validator.js" />
</response>
</test>
<test ID="getOrders">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-number-post.json</filename>
<vars>
<var ID="COUNT">4</var>
</vars>
<response>
<validator lang="javascript" filename="_self_test/res/getOrders.validator.js" />
</response>
</test>
<test ID="deleteOrders" loop="${size(getOrders.ORDER_IDS)}">
<method>GET</method>
<uri>/tagonomy?mock=${getOrders.ORDER_IDS[this.LoopIndex]}</uri>
</test>
<test ID="useValidatorExpectErrors">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-number-post.json</filename>
<vars>
<var ID="COUNT">3</var>
</vars>
<response>
<expected>
<failure />
</expected>
<validator lang="javascript" filename="_self_test/res/selftest-with-validator-errors.validator.js" />
</response>
</test>
<test ID="emptyExpectedResponseFile">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-number-post.json</filename>
<vars>
<var ID="COUNT">3</var>
</vars>
<response>
<filename>_self_test/res/empty-file.json</filename>
</response>
</test>
<test ID="jsonBadPropertyNames">
<method>PUT</method>
<expected>
<code range="202" />
</expected>
<uri>http://localhost:${SELFTEST_PORT}/tagonomy?mock=true&amp;mutation=${this.mutation}&amp;emptyMutationResponseCode=202</uri>
<filename>_self_test/json-bad-propertynames.json</filename>
<vars>
<var ID="DUE_DATE_MILLIS">${tools.now()}</var>
<var ID="VarTestMessage">Base message set here as default (useVarMutator).</var>
</vars>
<response>
<expected dom="TEXT" />
</response>
</test>
<test ID="useVarMutator">
<method>PUT</method>
<expected>
<code range="202" />
<comment>because emptyMutationResponseCode=202 is sent in uri.
Each non-empty mutation (child test) will return a 406, hardcoded on the server side of this test,
because typical use case is seeing if removing fields makes the service complain.</comment>
</expected>
<uri>http://localhost:${SELFTEST_PORT}/tagonomy?mock=true&amp;mutation=${this.mutation}&amp;emptyMutationResponseCode=202</uri>
<filename>_self_test/var-mutator-test.json</filename>
<vars>
<var ID="DAYS">${24*60*60*1000}</var>
<var ID="BASE_DATE">${tools.now()}</var>
<var ID="DUE_DATE_MILLIS">${BASE_DATE +0 * DAYS}</var>
<var ID="DueDate">Due ${kit.dates.getMonthName(BASE_DATE)} ${kit.dates.getDayOfMonth(BASE_DATE)}</var>
<var ID="VarTestMessage">Base message set here as default (useVarMutator).</var>
</vars>
<mutator type="VarMutator">
<expected>
<code range="406" />
</expected>
<vars ID="0">
<var idbase="DUE_DATE_MILLIS">${BASE_DATE +1 * DAYS}</var>
<var idbase="VarTestMessage">${this.testID} set in mutation ID=0.</var>
</vars>
<vars ID="1">
<var idbase="DUE_DATE_MILLIS">${BASE_DATE +3 * DAYS}</var>
<var idbase="VarTestMessage">${this.testID} set in mutation ID=1.</var>
</vars>
</mutator>
</test>
<test ID="filenameExpressions" skipParent="true">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<mutator type="VarMutator" skipParent="true">
<comment>This *sort of* works with skipParent=false, because EXPECTED_FILE is still
in the shared context from the last go-round of AddedChanged,
when the parent expected/filename gets eval'd,
even though the parent doesn't set up that variable.
For now, we're going to recommend using VarMutators ONLY with skipParents=true.
</comment>
<vars ID="Base">
<var idbase="EXPECTED_FILE">_self_test/res/jsonTreeCompareL.xml</var>
</vars>
<vars ID="AddedChanged">
<var idbase="EXPECTED_FILE">_self_test/res/jsonTreeCompareAddedChangedL.xml</var>
</vars>
</mutator>
<response>
<expected dom="TEXT" />
<filename>${EXPECTED_FILE}</filename>
</response>
</test>
<test ID="filenameExpressionExports">
<comment>In this one, the expression gets evaluated twice:
1) in EXPECTED_FILE,
2) in EXPECTED_FILENAME_EXPORTED.
This really just shows that exports and vars are both available to filename expressions.
</comment>
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<mutator type="VarMutator" skipParent="true">
<vars ID="Base">
<var idbase="EXPECTED_FILE">_self_test/res/jsonTreeCompareL.xml</var>
</vars>
<vars ID="Changed">
<var idbase="EXPECTED_FILE">_self_test/res/jsonTreeCompareChangedL.xml</var>
</vars>
</mutator>
<exports>
<vars>
<var ID="EXPECTED_FILENAME_EXPORTED">${EXPECTED_FILE}</var>
</vars>
</exports>
<response>
<expected dom="TEXT" />
<filename>${EXPECTED_FILENAME_EXPORTED}</filename>
</response>
</test>
<test ID="fullPathFilename">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<response>
<filename>/Users/vcrocla/src/RestReplay/run</filename>
</response>
</test>
<test ID="jsonTreeCompare">
<comment>This test checks one API's response against three expected possibilities,
by looping three times, and supplying three different filenames, and using the same
validation strategy, but reading three different validation templates.</comment>
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<comment>we are just sending jsonTreeCompareL.xml as content because we have to send something.
The service echos back the payload, and sets a mime header for the type specified
by the query parmeter mimeOut.
</comment>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<mutator type="VarMutator" skipParent="true">
<vars ID="Base">
<var idbase="REQUEST_FILE" >_self_test/res/jsonTreeCompareL.xml</var>
<var idbase="EXPECTED_FILE">_self_test/res/jsonTreeCompareL.xml</var>
</vars>
<vars ID="Added">
<var idbase="REQUEST_FILE" >_self_test/res/jsonTreeCompareAddedL.xml</var>
<var idbase="EXPECTED_FILE">_self_test/res/jsonTreeCompareAddedL.xml</var>
</vars>
<vars ID="Changed">
<var idbase="REQUEST_FILE" >_self_test/res/jsonTreeCompareChangedL.xml</var>
<var idbase="EXPECTED_FILE">_self_test/res/jsonTreeCompareChangedL.xml</var>
</vars>
<vars ID="AddedChanged">
<var idbase="REQUEST_FILE" >_self_test/res/jsonTreeCompareAddedChangedL.xml</var>
<var idbase="EXPECTED_FILE">_self_test/res/jsonTreeCompareAddedChangedL.xml</var>
</vars>
<expected>
<dom>
<MATCHED range="3" />
<DIFFERENT range="0" />
</dom>
</expected>
</mutator>
<response>
<expected>
<dom>
<MATCHED range="3" />
<DIFFERENT range="0" />
</dom>
</expected>
<filename>${EXPECTED_FILE}</filename>
</response>
</test>
<test ID="jsonTreeCompareTextChanged">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<response>
<expected dom="ADDOK">
<failure />
</expected>
<filename>_self_test/res/jsonTreeCompareChangedL.xml</filename>
</response>
</test>
<test ID="jsonTreeCompareRange">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<response>
<expected>
<dom>
<DIFFERENT range="0-2"></DIFFERENT>
</dom>
</expected>
<filename>_self_test/res/jsonTreeCompareChangedL.xml</filename>
</response>
</test>
<test ID="jsonTreeCompareCustom">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<response>
<expected>
<dom>
<MATCHED range="1"></MATCHED>
<REMOVED range="0"></REMOVED>
<ADDED range="0"></ADDED>
<ERROR range="0"></ERROR>
<DIFFERENT range="2"></DIFFERENT>
<NESTED_ERROR range="0"></NESTED_ERROR>
</dom>
</expected>
<filename>_self_test/res/jsonTreeCompareChangedL.xml</filename>
</response>
</test>
<test ID="jsonTreeCompareJustDifferences">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<response>
<expected>
<dom>
<DIFFERENT range="2"></DIFFERENT>
</dom>
</expected>
<filename>_self_test/res/jsonTreeCompareChangedL.xml</filename>
<was>jsonTreeCompareChangedL</was>
</response>
</test>
<test ID="ToSpecifyBothIsAnError">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<response>
<expected dom="ADDOK">
<failure />
<dom>
<DIFFERENT range="2"></DIFFERENT>
</dom>
</expected>
<filename>_self_test/res/jsonTreeCompareChangedL.xml</filename>
</response>
</test>
<test ID="jsonCompareOrders">
<method>POST</method>
<uri>/jsonCompare1</uri>
<filename>_self_test/jsonCompareOrders.json</filename>
<vars>
<var ID="TITLE">Order for Smith - 123400</var>
</vars>
<response>
<expected dom="ADDOK" />
<filename>_self_test/res/jsonCompareOrders.json</filename>
</response>
</test>
<test ID="jsonCompareOrders_ExpectedIsXml">
<method>POST</method>
<uri>/jsonCompare1</uri>
<filename>_self_test/jsonCompareOrders.json</filename>
<vars>
<var ID="TITLE">Order for Smith - 123400</var>
</vars>
<response>
<expected dom="ADDOK" />
<filename>_self_test/res/jsonCompareOrders.xml</filename>
</response>
</test>
<test ID="jsonCompareOrders_ExpectedIsXmlNewRoot">
<method>POST</method>
<uri>/jsonCompare1</uri>
<filename>_self_test/jsonCompareOrders.json</filename>
<vars>
<var ID="TITLE">Order for Smith - 123400</var>
</vars>
<response>
<expected dom="ADDOK" />
<filename>_self_test/res/jsonCompareOrdersNewRoot.xml</filename>
</response>
</test>
<test ID="headersFromGet">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<comment>Ensure that ACCEPT headers and all other headers condense properly</comment>
<headers>
<header name="Accept">application/json</header>
<header name="Accept">text/json</header>
</headers>
<exports>
<vars>
<var ID="Content-length">${this.get('Content-length')}</var>
<var ID="CONTENT-LENGTH">${this.get('CONTENT-LENGTH')}</var>
<var ID="Accept">${this.get('Accept')}</var>
<var ID="ACCEPT">${this.get('ACCEPT')}</var>
</vars>
</exports>
</test>
<!--"problem": "This file starts with an array, but never ends it."" if needed: /jsonCompare1?mimeOut=text/json-->
<test ID="badJson">
<method>POST</method>
<uri>/jsonCompare1</uri>
<filename>_self_test/bad-json.json</filename>
</test>
</testGroup>
<testGroup ID="testMutatorExpectedCodes" autoDeletePOSTS="false">
<test ID="varMutatorExpectedCodes">
<method>PUT</method>
<uri>/tagonomy?mock=true&amp;mutation=${this.mutation}&amp;emptyMutationResponseCode=401</uri>
<filename>_self_test/var-mutator-test.json</filename>
<expected>
<code range="401">*</code>
</expected>
<vars>
<var ID="DAYS">${24*60*60*1000}</var>
<var ID="BASE_DATE">${tools.now()}</var>
<var ID="DUE_DATE_MILLIS">${BASE_DATE +0 * DAYS}</var>
<var ID="FOOBAR">${this.testID}</var>
<var ID="DueDate2">Due ${BASE_DATE} -basedate</var>
<var ID="DueDate">Due ${kit.dates.getMonthName(BASE_DATE)} ${kit.dates.getDayOfMonth(BASE_DATE)}</var>
<var ID="VarTestMessage">Base message set here as default (varMutatorExpectedCodes).</var>
</vars>
<mutator type="VarMutator">
<expected>
<code range="406">*</code>
</expected>
<vars ID="0">
<var idbase="DUE_DATE_MILLIS">${BASE_DATE +1 * DAYS}</var>
<var idbase="FOOBAR">${this.testID} set in 0.</var>
</vars>
<vars ID="1">
<var idbase="DUE_DATE_MILLIS">${BASE_DATE +2 * DAYS}</var>
<var idbase="FOOBAR">${this.testID + ' mutator index: ' + this.mutator.getIndex() }</var>
</vars>
</mutator>
</test>
<test ID="ExcludeFieldsMutatorExpectedCodes">
<method>PUT</method>
<uri>/tagonomy?mock=true&amp;mutation=${this.mutation}</uri>
<filename>_self_test/selftest-mutator.json</filename>
<expected>
<code range="2x"/>
</expected>
<vars>
<var ID="TOKEN">FOOTOKEN</var>
<var ID="mutation">${this.mutation}</var>
</vars>
<mutator type="ExcludeFields">
<expected>
<code range="202">no_optionalField</code>
<code range="4x">*</code>
</expected>
</mutator>
</test>
</testGroup>
<testGroup ID="VarsAndValidators">
<test ID="exportVarsFromJexl">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<exports>
<vars>
<var ID="OFFSET"><![CDATA[${
arr = kit.newStringArray(3);
arr[0]="10";
arr[1]="18";
arr[2]="21";
return arr;
}]]></var>
</vars>
<vars>
<var ID="OFFSET_LITERAL"><![CDATA[${
arr = ['20', '33', '128'];
return arr;
}]]></var>
<var ID="OFFSET_LITERAL_SINGLE">${['21','34','129']}</var>
</vars>
</exports>
</test>
<test ID="useVarValidator">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<vars>
<var ID="ARRAYS_USED_0">OFFSET: ${exportVarsFromJexl.OFFSET[0]}, ${exportVarsFromJexl.OFFSET[1]}, ${exportVarsFromJexl.OFFSET[2]}</var>
<var ID="ARRAYS_USED_1">OFFSET_LITERAL: ${exportVarsFromJexl.OFFSET_LITERAL[0]}, ${exportVarsFromJexl.OFFSET_LITERAL[1]}, ${exportVarsFromJexl.OFFSET_LITERAL[2]}</var>
<var ID="ARRAYS_USED_2">OFFSET_LITERAL_SINGLE: ${exportVarsFromJexl.OFFSET_LITERAL_SINGLE[0]}, ${exportVarsFromJexl.OFFSET_LITERAL_SINGLE[1]}, ${exportVarsFromJexl.OFFSET_LITERAL_SINGLE[2]}</var>
<var ID="theOFFSET0">${exportVarsFromJexl.OFFSET[0]}</var>
</vars>
<response>
<expected>
<failure />
</expected>
<validator lang="javascript"><![CDATA[
if (exportVarsFromJexl.get('OFFSET')[1] != '9'){
serviceResult.addError("OFFSET[1] was not 9, was: "+exportVarsFromJexl.get('OFFSET')[1]);
}
if (theOFFSET0 != '9'){
serviceResult.addWarning("theOFFSET0 was not 9, was: "+theOFFSET0);
}
]]></validator>
</response>
</test>
<test ID="useVarValidatorNoErrors">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=text/xml</uri>
<filename>_self_test/res/jsonTreeCompareL.xml</filename>
<vars>
<var ID="ARRAYS_USED_0">OFFSET: ${exportVarsFromJexl.OFFSET[0]}, ${exportVarsFromJexl.OFFSET[1]}, ${exportVarsFromJexl.OFFSET[2]}</var>
<var ID="ARRAYS_USED_1">OFFSET_LITERAL: ${exportVarsFromJexl.OFFSET_LITERAL[0]}, ${exportVarsFromJexl.OFFSET_LITERAL[1]}, ${exportVarsFromJexl.OFFSET_LITERAL[2]}</var>
<var ID="ARRAYS_USED_2">OFFSET_LITERAL_SINGLE: ${exportVarsFromJexl.OFFSET_LITERAL_SINGLE[0]}, ${exportVarsFromJexl.OFFSET_LITERAL_SINGLE[1]}, ${exportVarsFromJexl.OFFSET_LITERAL_SINGLE[2]}</var>
<var ID="theOFFSET0">${exportVarsFromJexl.OFFSET[0]}</var>
</vars>
<response>
<validator lang="javascript"><![CDATA[
if (exportVarsFromJexl.get('OFFSET')[1] != '18'){
serviceResult.addError("OFFSET[1] was not 18, was: "+exportVarsFromJexl.get('OFFSET')[1]);
}
if (theOFFSET0 != '10'){
serviceResult.addWarning("theOFFSET0 was not 10, was: "+theOFFSET0);
}
]]></validator>
</response>
</test>
</testGroup>
<testGroup ID="Mastervars">
<test ID="showMastervars">
<method>GET</method>
<uri>/tagonomy?mock=token&amp;GLOBALMASTERVAR1=${GLOBALMASTERVAR1}&amp;MASTERVAR1=${MASTERVAR1}</uri>
<vars>
<var ID="MV1">${MASTERVAR1}</var>
</vars>
<exports>
<vars>
<var ID="MV2">${MASTERVAR2}</var>
</vars>
</exports>
</test>
</testGroup>
<testGroup ID="ImportedRunVars">
<test ID="showImportedVar">
<method>GET</method>
<uri>/tagonomy?mock=token&amp;imported=${VAR_VALUE}&amp;end=1</uri>
</test>
</testGroup>
<testGroup ID="Loops" autoDeletePOSTS="true">
<test ID="loopStringArraySimple" loop="${['10','18','21']}">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<vars>
<var ID="someArray">${["103","183","213"]}</var>
<var ID="LOOP">${loop}</var>
</vars>
</test>
<test ID="createResourceToAutodelete">
<comment>Show when service returns body text, during autodelete.</comment>
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-token-post.json</filename>
</test>
<test ID="loopStringArray" loop="${['10','18','21']}">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=application/json</uri>
<filename>_self_test/loop-dates.json</filename>
<vars>
<var ID="DAYS">${24*60*60*1000}</var>
<var ID="someArray">${["103","183","213"]}</var>
<var ID="useSomeArray">${someArray[this.LoopIndex]*DAYS}</var>
<var ID="LOOPSIZE">${"size: "+size(loop)}</var>
<var ID="LOOP_THIS_INDEX">${"loop[this.LoopIndex]: "+loop[this.LoopIndex]}</var>
<var ID="LOOP_INDEX">${"loop[loop.index]: "+loop[loop.index]}</var>
<var ID="LOOP_VALUE">${loop.value}</var>
<var ID="LOOP_OBJECT">${loop.object}</var>
<var ID="DUE_DATE_MILLIS">${tools.now() + loop.value*DAYS}</var>
<var ID="INSTRUCTOR_NOTE">Dr. L sez, assignment for ${DUE_DATE_MILLIS} ${this.testID}</var>
<var ID="TITLE">Due ${kit.dates.getMonthName(DUE_DATE_MILLIS)} ${kit.dates.getDayOfMonth(DUE_DATE_MILLIS)}</var>
</vars>
<response>
<expected>
<dom>
<REMOVED range="0" />
<DIFFERENT range="0" />
</dom>
</expected>
<filename>_self_test/res/loop-dates.json</filename>
</response>
</test>
<test ID="loopMap" loop="${{'a':'Due February 20','b':'Due January 28'}}">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=application/json</uri>
<filename>_self_test/loop-dates.json</filename>
<vars>
<var ID="LOOP_MAP_INFO">${"size: "+size(loop)+", loop.key: "+loop.key+", loop.value:"+loop.value+", loop['"+loop.key+"']: "+loop[loop.key]}</var>
<var ID="DUE_DATE_MILLIS">${24*60*60*1000}</var>
<var ID="INSTRUCTOR_NOTE">${loop.key}</var>
<var ID="TITLE">${loop.value}</var>
<var ID="LOOP">${loop}</var>
</vars>
<response>
<expected>
<dom>
<REMOVED range="0" />
<DIFFERENT range="0" />
</dom>
</expected>
<filename>_self_test/res/loop-dates.json</filename>
</response>
</test>
<test ID="LoopArrayOfMap" loop="${[{'a':'aVal', 'b':'bVal'},{'c':'cVal', 'd':'dVal'}]}">
<method>GET</method>
<uri>/jsonCompare1?mimeOut=application/json&amp;loop=${this.LoopIndex}</uri>
<vars>
<var ID="VALUE_a">${loop.value.a}</var>
<var ID="VALUE_c">${loop.value.c}</var>
<var ID="VALUE">${loop.value}</var>
<var ID="LOOP">${loop}</var>
</vars>
</test>
<test ID="LoopArrayOfMap2">
<loop>
${[{'USER':'Moe Gibbons', 'ORDER':'AM444890'},
{'USER':'Clive Orvis', 'ORDER':'AC897654'}
]}
</loop>
<method>GET</method>
<uri>/jsonCompare1?mimeOut=application/json&amp;LoopIndex=${this.LoopIndex}&amp;loop.index=${loop.index}</uri>
<vars>
<var ID="ORDER">${loop.value.ORDER}</var>
<var ID="USER">${loop.value.USER}</var>
</vars>
</test>
<test ID="loopValidatorNoLoop">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/content-mutator-test.json</filename>
<response>
<validator lang="javascript"><![CDATA[
if (loop){
var ret = {'index': loop.index, 'value': loop.value};
" loop: "+loop+" ret.index: "+ret.index+" loop.object:"+loop.object;
} else {
"loop var not available";
}
]]></validator>
</response>
</test>
<test ID="loopValidator" loop="2">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/content-mutator-test.json</filename>
<response>
<validator lang="javascript"><![CDATA[
if (loop){
var ret = {'index': loop.index, 'value': loop.value};
" loop: "+loop+" ret.index: "+ret.index+" loop.object:"+loop.object;
} else {
"loop var not available";
}
]]></validator>
</response>
</test>
<test ID="loopValidatorWMap">
<loop>
${{'USER':'Moe Gibbons', 'ORDER':'AM444890'}}
</loop>
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/content-mutator-test.json</filename>
<response>
<validator lang="javascript"><![CDATA[
if (loop){
var ret = {'index': loop.index, 'value': loop.value};
serviceResult.addExport("CurrentItem",loop.key+"::"+loop.value);
" loop: "+loop+", ret.index: "+ret.index+" loop.object:"+loop.object;
} else {
"loop var not available";
}
]]></validator>
</response>
</test>
<test ID="loopValidatorWArrayOfMap">
<loop>
${[{'USER':'Moe Gibbons', 'ORDER':'AM444890'},
{'USER':'Clive Orvis', 'ORDER':'AC897654'}
]}
</loop>
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/content-mutator-test.json</filename>
<response>
<validator lang="javascript"><![CDATA[
if (loop){
var ret = {'index': loop.index, 'value': loop.value};
serviceResult.addExport("Order",""+ loop.value.get("USER")+" ordered: "+ loop.value.get("ORDER"));
" loop: "+loop+", ret.index: "+ret.index+" loop.object:"+loop.object;
} else {
"loop var not available";
}
]]></validator>
</response>
</test>
<test ID="BadLoopExpression" loop="${this+is+a+syntax:error}">
<method>GET</method>
<uri>/jsonCompare1?mimeOut=application/json</uri>
<vars>
<var ID="TITLE">${loop.value}</var>
</vars>
<response>
<expected>
<failure />
</expected>
</response>
</test>
<test ID="MapInVar">
<method>GET</method>
<uri>/tagonomy?mock=true</uri>
<header name="Content-Type">application/json</header>
<vars>
<var ID="BAR">NIXON</var>
<var ID="MAP">
${{"DAY_3":"CREATE","DAY_4":"DELETE"}}
</var>
</vars>
<response>
<validator lang="javascript"><![CDATA[
var ACTION = serviceResult.get("MAP").get("DAY_3")
if (!ACTION.equals("CREATE")){
serviceResult.addError("Value of map ("+ACTION+") didn't match \"CREATE\"");
}
]]></validator>
</response>
</test>
</testGroup>
<testGroup ID="deleteURLs">
<test ID="useURL">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<exports>
<vars>
<var ID="protocol">${result.url.protocol}</var>
<var ID="authority">${result.url.authority}</var>
<var ID="path">${result.url.path}</var>
<var ID="protoHostPort">${result.protoHostPort}</var>
</vars>
</exports>
</test>
<test ID="useURLCreateDeleteURL">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<deleteURL>${result.url.protocol}://${result.url.authority}${result.url.path}?${result.url.query}</deleteURL>
</test>
<test ID="use_fullURL">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<deleteURL>${result.fullURL}</deleteURL>
</test>
<test ID="goodDeleteURL">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<headers>
<header name="x-authorization">MOJO</header>
<header name="x-my-variable">NIXON</header>
</headers>
<deleteURL>${result.fullURL}</deleteURL>
</test>
<test ID="badDeleteURL">
<method>GET</method>
<uri>/tagonomy?mock=token</uri>
<deleteURL>BadURL://${result.fullURL}</deleteURL>
<response>
<expected>
<failure />
</expected>
</response>
</test>
</testGroup>
<testGroup ID="badResourcePaths" autoDeletePOSTS="false">
<test ID="missingDirectory">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=application/json</uri>
<filename>_self_test/bad-directory/loop-dates.json</filename>
</test>
<test ID="missingFile">
<method>POST</method>
<uri>/jsonCompare1?mimeOut=application/json</uri>
<filename>_self_test/no-file-here.json</filename>
</test>
</testGroup>
<testGroup ID="useImports" autoDeletePOSTS="false">
<imports>
<import ID="myImportedTokenTest" control="_self_test/self-test.xml" testGroup="login" test="token" />
</imports>
<headers>
<header ID="x-mojo-auth">${myImportedTokenTest.exportedToken}</header>
</headers>
<test ID="importer">
<method>GET</method>
<uri>/tagonomy?mock=true&amp;TOKEN_ID=${TOKEN_ID}</uri>
<vars>
<var ID="TOKEN_ID">${myImportedTokenTest.status}</var>
</vars>
</test>
</testGroup>
<testGroup ID="badImports" autoDeletePOSTS="false">
<comment>An invalid imports block or import statement in a testGroup
invalidates the testGroup so that no tests in the group are run.
This testGroup imports resources that don't exist, each named by their fault.
This test expects that an error message will
display the errors about the testGroup, but not run any tests.
</comment>
<imports>
<import ID="myImportedTokenTestGOOD" control="_self_test/self-test.xml" testGroup="login" test="token" />
<import ID="myImportedTokenTestBAD1" control="_self_test/self-test.xml" testGroup="login" test="tokenWRONG" />
<import ID="myImportedTokenTestBAD2" control="_self_test/self-test.xml" testGroup="loginWRONG" test="token" />
<import ID="myImportedTokenTestBAD3" control="_self_test/self-test.xmlWRONG" testGroup="login" test="token" />
</imports>
<headers>
<header ID="x-mojo-auth">${myImportedTokenTest.exportedToken}</header>
</headers>
<test ID="importer">
<method>GET</method>
<uri>${SELFTEST_SERVER}/tagonomy?mock=true&amp;foo=${TOKEN_ID}</uri>
<vars>
<var ID="TOKEN_ID">${myImportedTokenTest.status}</var>
</vars>
</test>
</testGroup>
<testGroup ID="commentsGroup" autoDeletePOSTS="false">
<comment><a href="">FEATURE-1393</a> Implement comments in testGroups.
&lt;comment> tags should be able to include any HTML markup, such as unordered lists:
<ul>
<li>First point about testGroup</li>
<li>Second point</li>
<li>Third point</li>
</ul>
<p>And paragraphs with <b>bold</b> and <i>italics</i>.</p>
<p>And tables with attributes:
<table border="1">
<tr>
<th colspan="2">title 1</th>
<th>title 2</th>
<th>title 3</th>
</tr>
<tr>
<th>1</th>
<td>cell r1,c1</td>
<td>cell r1,c2</td>
<td>cell r1,c3</td>
</tr>
<tr>
<th>2</th>
<td>cell r2,c1</td>
<td>cell r2,c2</td>
<td>cell r2,c3</td>
</tr>
</table>
</p>
End.
</comment>
<test ID="comments">
<comment><a href="">FEATURE-1394</a> Implement comments in tests. Should handle long text and short text.
Long text should be broken on the character limit
<a href="http://dynamide.org/RestReplay/javadoc/org/dynamide/restreplay/RunOptions.html#MAX_CHARS_FOR_COMMENT_SHORT">RunOptions.MAX_CHARS_FOR_COMMENT_SHORT</a>.
&lt;comment> tags should be able to include any HTML markup, such as unordered lists:
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
<p>And paragraphs with <b>bold</b> and <i>italics</i>.</p>
<p>
<table border="1">
<tr>
<th colspan="2">title 1</th>
<th>title 2</th>
<th>title 3</th>
</tr>
<tr>
<th>1</th>
<td>cell r1,c1</td>
<td>cell r1,c2</td>
<td>cell r1,c3</td>
</tr>
<tr>
<th>2</th>
<td>cell r2,c1</td>
<td>cell r2,c2</td>
<td>cell r2,c3</td>
</tr>
</table>
</p>
End.
</comment>
<uri>/tagonomy?mock=token</uri>
</test>
</testGroup>
<testGroup ID="debug" autoDeletePOSTS="true">
<test ID="uploadBinary">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<upload>
<filename>/Users/vcrocla/src/RestReplay/src/main/resources/restreplay/_self_test/upload/q/favicon.ico</filename>
</upload>
</test>
<test ID="varWithFilename">
<method>GET</method>
<uri>/tagonomy?mock=true</uri>
<vars>
<var ID="TITLE">My Title</var>
<var ID="INSTRUCTOR_NOTE">My long note.</var>
<var ID="DUE_DATE_MILLIS">${tools.now()}</var>
<var ID="VAR_IN_FILE" filename="_self_test/loop-dates.json"></var>
</vars>
</test>
</testGroup>
<testGroup ID="debugHAR" autoDeletePOSTS="true">
<test ID="ViewHTTPArchives">
<comment>This test lets you see the top-level elements in the object saved by Chrome's "save to HAR".
As masterVar "INFILE", pass the full or relative path to your .har file, e.g.
<code>chrome-sessions/my-session.har</code></comment>
<method>NOOP</method>
<uri>/tagonomy?mock=token</uri>
<vars>
<var ID="INFILE">/Users/vcrocla/tmp/restreplay-local-tests/revel-chrome-sessions/console-stg.pearson.com-delete-course.har</var>
</vars>
<response>
<note>Validator script uses result.expectedResponse as input file.</note>
<filename>${INFILE}</filename>
<validator lang="javascript" filename="_self_test/s/ViewHTTPArchives.validator.js" />
<novalidator lang="javascript">var f='hi';f;</novalidator>
</response>
</test>
</testGroup>
<testGroup ID="BUGS_TODO" autoDeletePOSTS="false">
<test ID="useTokenPUTbugs">
<!-- This case causes errors to happen in the mutated child tests, but reading the json response borks the
parent so it doesn't display correctly, and the children seem like top-level tests.
Trace this to the code that breaks on the error and trap the error correctly.
-->
<method>PUT</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-mutator.json</filename>
<mutator type="ExcludeFields">
<expected>
<code range="4xx">*</code>
</expected>
</mutator>
<exports>
<vars>
<var ID="plainString">${tools.encodeURLString("and these are my data 1 2 3 + % * left-brace:\u007B right-brace:\u007D ")}</var>
<var ID="encodedData2">${tools.encodeURLString(this.got("//data"))}</var>
<var ID="data">${this.got("//data")}</var>
<var ID="result">This case (result/this) is borked: ${result.got("//data")}</var>
<var ID="returnTest">${var d = this.got("//data"); if (d.length()>0) {return true;} else {return false;}}</var>
</vars>
</exports>
</test>
<test ID="selftestUseData" autoDeletePOSTS="false">
<method>GET</method>
<uri>/tagonomy?mock=token&amp;data=${tools.encodeURLString(useTokenPUTbugs.result)}</uri>
</test>
<test ID="useToken">
<!-- this one works above, but had this warning comment. If you need to look into it, the case and the comment are here.-->
<method>GET</method>
<uri>/tagonomy?mock=true&amp;name=useToken</uri>
<headers>
<header name="x-authorization">${token.got("//data")}</header>
<header name="x-method">${token.method}</header>
</headers>
<!--This causes a warning. And it breaks auto delete with the erroneous url.
Keeping this here for development of two error tests.
TODO: Develop tests that fire these, and also demonstrate the ways to construct a url, and a deleteURL.
<deleteURL>${result.url.protocol}://${result.url.authority}${result.url.path} -:: ${result.protoHostPort} ::-</deleteURL>
-->
</test>
</testGroup>
<testGroup ID="debugScript">
<test ID="selftestReturnTest">
<method>POST</method>
<uri>/tagonomy?mock=true</uri>
<filename>_self_test/selftest-mutator.json</filename>
</test>
</testGroup>
</restReplay>