@@ -13,24 +13,24 @@ governing permissions and limitations under the License.
1313/* ************* NOTE 1: these tests must be run sequentially, jest does it by default within a SINGLE file ************* */
1414/* ************* NOTE 2: requires env vars TEST_AUTH_1, TEST_NS_1 and TEST_AUTH_2, TEST_NS_2 for 2 different namespaces. ************* */
1515
16- const path = require ( 'node:path' )
17-
18- // load .env values in the e2e folder, if any
19- require ( 'dotenv' ) . config ( { path : path . join ( __dirname , '.env' ) } )
20-
21- const { MAX_TTL_SECONDS } = require ( '../lib/constants' )
2216const stateLib = require ( '../index' )
17+ const { codes } = require ( '../lib/StateStoreError' )
2318
2419const testKey = 'e2e_test_state_key'
2520
2621jest . setTimeout ( 30000 ) // thirty seconds per test
2722
23+ beforeEach ( ( ) => {
24+ expect . hasAssertions ( )
25+ } )
26+
2827const initStateEnv = async ( n = 1 ) => {
2928 delete process . env . __OW_API_KEY
3029 delete process . env . __OW_NAMESPACE
3130 process . env . __OW_API_KEY = process . env [ `TEST_AUTH_${ n } ` ]
3231 process . env . __OW_NAMESPACE = process . env [ `TEST_NAMESPACE_${ n } ` ]
33- const state = await stateLib . init ( )
32+ // 1. init will fetch credentials from the tvm using ow creds
33+ const state = await stateLib . init ( ) // { tvm: { cacheFile: false } } // keep cache for better perf?
3434 // make sure we delete the testKey, note that delete might fail as it is an op under test
3535 await state . delete ( testKey )
3636 return state
@@ -44,83 +44,82 @@ describe('e2e tests using OpenWhisk credentials (as env vars)', () => {
4444 delete process . env . __OW_NAMESPACE
4545 process . env . __OW_API_KEY = process . env . TEST_AUTH_1
4646 process . env . __OW_NAMESPACE = process . env . TEST_NAMESPACE_1 + 'bad'
47- let expectedError
4847
4948 try {
50- const store = await stateLib . init ( )
51- await store . get ( 'something' )
49+ await stateLib . init ( )
5250 } catch ( e ) {
53- expectedError = e
54- }
55-
56- expect ( expectedError ) . toBeDefined ( )
57- expect ( expectedError instanceof Error ) . toBeTruthy ( )
58- expect ( { name : expectedError . name , code : expectedError . code , message : expectedError . message , sdkDetails : expectedError . sdkDetails } )
59- . toEqual ( expect . objectContaining ( {
60- name : 'AdobeStateLibError' ,
51+ expect ( { name : e . name , code : e . code , message : e . message , sdkDetails : e . sdkDetails } ) . toEqual ( expect . objectContaining ( {
52+ name : 'StateLibError' ,
6153 code : 'ERROR_BAD_CREDENTIALS'
6254 } ) )
55+ }
6356 } )
6457
65- test ( 'key-value basic test on one key with string value: put, get, delete, any, deleteAll ' , async ( ) => {
58+ test ( 'key-value basic test on one key with string value: get, write, get, delete, get ' , async ( ) => {
6659 const state = await initStateEnv ( )
6760
6861 const testValue = 'a string'
6962
7063 expect ( await state . get ( testKey ) ) . toEqual ( undefined )
7164 expect ( await state . put ( testKey , testValue ) ) . toEqual ( testKey )
7265 expect ( await state . get ( testKey ) ) . toEqual ( expect . objectContaining ( { value : testValue } ) )
73- expect ( await state . delete ( testKey ) ) . toEqual ( testKey )
66+ expect ( await state . delete ( testKey , testValue ) ) . toEqual ( testKey )
67+ expect ( await state . get ( testKey ) ) . toEqual ( undefined )
68+ } )
69+
70+ test ( 'key-value basic test on one key with object value: get, write, get, delete, get' , async ( ) => {
71+ const state = await initStateEnv ( )
72+
73+ const testValue = { a : 'fake' , object : { with : { multiple : 'layers' } , that : { dreams : { of : { being : 'real' } } } } }
74+
7475 expect ( await state . get ( testKey ) ) . toEqual ( undefined )
75- expect ( await state . any ( ) ) . toEqual ( false )
7676 expect ( await state . put ( testKey , testValue ) ) . toEqual ( testKey )
77- expect ( await state . any ( ) ) . toEqual ( true )
78- expect ( await state . deleteAll ( ) ) . toEqual ( true )
77+ expect ( await state . get ( testKey ) ) . toEqual ( expect . objectContaining ( { value : testValue } ) )
78+ expect ( await state . delete ( testKey , testValue ) ) . toEqual ( testKey )
7979 expect ( await state . get ( testKey ) ) . toEqual ( undefined )
80- expect ( await state . any ( ) ) . toEqual ( false )
8180 } )
8281
8382 test ( 'time-to-live tests: write w/o ttl, get default ttl, write with ttl, get, get after ttl' , async ( ) => {
8483 const state = await initStateEnv ( )
8584
86- const testValue = 'test value'
87- let res , resTime
85+ const testValue = { an : 'object' }
8886
8987 // 1. test default ttl = 1 day
9088 expect ( await state . put ( testKey , testValue ) ) . toEqual ( testKey )
91- res = await state . get ( testKey )
92- resTime = new Date ( res . expiration ) . getTime ( )
93- expect ( resTime ) . toBeLessThanOrEqual ( new Date ( Date . now ( ) + 86400000 ) . getTime ( ) ) // 86400000 ms = 1 day
94- expect ( resTime ) . toBeGreaterThanOrEqual ( new Date ( Date . now ( ) + 86400000 - 10000 ) . getTime ( ) ) // give more or less 10 seconds clock skew + request time
89+ let res = await state . get ( testKey )
90+ expect ( new Date ( res . expiration ) . getTime ( ) ) . toBeLessThanOrEqual ( new Date ( Date . now ( ) + 86400000 ) . getTime ( ) ) // 86400000 ms = 1 day
91+ expect ( new Date ( res . expiration ) . getTime ( ) ) . toBeGreaterThanOrEqual ( new Date ( Date . now ( ) + 86400000 - 10000 ) . getTime ( ) ) // give more or less 10 seconds clock skew + request time
9592
96- // 2. test max ttl
97- const nowPlus365Days = new Date ( MAX_TTL_SECONDS ) . getTime ( )
93+ // 2. test infinite ttl
9894 expect ( await state . put ( testKey , testValue , { ttl : - 1 } ) ) . toEqual ( testKey )
99- res = await state . get ( testKey )
100- resTime = new Date ( res . expiration ) . getTime ( )
101- expect ( resTime ) . toBeGreaterThanOrEqual ( nowPlus365Days )
95+ expect ( await state . get ( testKey ) ) . toEqual ( expect . objectContaining ( { expiration : null } ) )
10296
10397 // 3. test that after ttl object is deleted
10498 expect ( await state . put ( testKey , testValue , { ttl : 2 } ) ) . toEqual ( testKey )
10599 res = await state . get ( testKey )
106100 expect ( new Date ( res . expiration ) . getTime ( ) ) . toBeLessThanOrEqual ( new Date ( Date . now ( ) + 2000 ) . getTime ( ) )
107- await waitFor ( 3000 ) // give it one more sec - ttl is not so precise
101+ await waitFor ( 3000 ) // give it one more sec - azure ttl is not so precise
108102 expect ( await state . get ( testKey ) ) . toEqual ( undefined )
109103 } )
110104
111105 test ( 'throw error when get/put with invalid keys' , async ( ) => {
112- const invalidKey = 'some/invalid/key'
106+ const invalidChars = "The following characters are restricted and cannot be used in the Id property: '/', '\\', '?', '#' "
107+ const invalidKey = 'invalid/key'
113108 const state = await initStateEnv ( )
114- await expect ( state . put ( invalidKey , 'testValue' ) ) . rejects . toThrow ( '[AdobeStateLib:ERROR_BAD_ARGUMENT] invalid key and/or value' )
115- await expect ( state . get ( invalidKey ) ) . rejects . toThrow ( '[AdobeStateLib:ERROR_BAD_ARGUMENT] invalid key' )
109+ await expect ( state . put ( invalidKey , 'testValue' ) ) . rejects . toThrow ( new codes . ERROR_BAD_REQUEST ( {
110+ messageValues : [ invalidChars ]
111+ } ) )
112+ await expect ( state . get ( invalidKey ) ) . rejects . toThrow ( new codes . ERROR_BAD_REQUEST ( {
113+ messageValues : [ invalidChars ]
114+ } ) )
116115 } )
117116
118117 test ( 'isolation tests: get, write, delete on same key for two namespaces do not interfere' , async ( ) => {
119118 const state1 = await initStateEnv ( 1 )
120119 const state2 = await initStateEnv ( 2 )
121120
122- const testValue1 = 'one value'
123- const testValue2 = 'some other value'
121+ const testValue1 = { an : 'object' }
122+ const testValue2 = { another : 'dummy' }
124123
125124 // 1. test that ns2 cannot get state in ns1
126125 await state1 . put ( testKey , testValue1 )
@@ -140,21 +139,16 @@ describe('e2e tests using OpenWhisk credentials (as env vars)', () => {
140139
141140 test ( 'error value bigger than 2MB test' , async ( ) => {
142141 const state = await initStateEnv ( )
142+
143143 const bigValue = ( 'a' ) . repeat ( 1024 * 1024 * 2 + 1 )
144- let expectedError
145144
146145 try {
147146 await state . put ( testKey , bigValue )
148147 } catch ( e ) {
149- expectedError = e
150- }
151-
152- expect ( expectedError ) . toBeDefined ( )
153- expect ( expectedError instanceof Error ) . toBeTruthy ( )
154- expect ( { name : expectedError . name , code : expectedError . code , message : expectedError . message , sdkDetails : expectedError . sdkDetails } )
155- . toEqual ( expect . objectContaining ( {
156- name : 'AdobeStateLibError' ,
148+ expect ( { name : e . name , code : e . code , message : e . message , sdkDetails : e . sdkDetails } ) . toEqual ( expect . objectContaining ( {
149+ name : 'StateLibError' ,
157150 code : 'ERROR_PAYLOAD_TOO_LARGE'
158151 } ) )
152+ }
159153 } )
160154} )
0 commit comments