11const assert = require ( 'assert' ) ;
2+ const fs = require ( 'fs' ) ;
3+ const net = require ( 'net' ) ;
24const connParameters = require ( './connectionParameters' ) ;
35const axios = require ( 'axios' ) ;
4- const { snowflakeAuthTestOktaUser , snowflakeAuthTestOktaPass , snowflakeAuthTestRole , snowflakeAuthTestOauthClientId,
6+ const { snowflakeAuthTestOauthClientId,
57 snowflakeAuthTestOauthClientSecret, snowflakeAuthTestOauthUrl
68} = require ( './connectionParameters' ) ;
79const AuthTest = require ( './authTestsBaseClass' ) ;
10+ const WireMockRestClient = require ( 'wiremock-rest-client' ) . WireMockRestClient ;
11+ const { exec } = require ( 'child_process' ) ;
812
913
14+
15+ async function runWireMockAsync ( port ) {
16+ let timeoutHandle ;
17+ const waitingWireMockPromise = new Promise ( async ( resolve , reject ) => {
18+ try {
19+ exec ( `npx wiremock --enable-browser-proxying --proxy-pass-through false --port ${ port } ` ) ;
20+ const wireMock = new WireMockRestClient ( `http://localhost:${ port } ` ) ;
21+ const readyWireMock = await waitForWiremockStarted ( wireMock ) ;
22+ resolve ( readyWireMock ) ;
23+ } catch ( err ) {
24+ reject ( err ) ;
25+ }
26+ } ) ;
27+
28+
29+ const timeout = new Promise ( ( resolve , reject ) =>
30+ timeoutHandle = setTimeout (
31+ ( ) => reject ( 'Wiremock unavailable after 6000 ms.' ) ,
32+ 6000 ) ) ;
33+ return Promise . race ( [ waitingWireMockPromise , timeout ] )
34+ . then ( result => {
35+ clearTimeout ( timeoutHandle ) ;
36+ return result ;
37+ } ) ;
38+ }
39+
40+ async function waitForWiremockStarted ( wireMock ) {
41+ return fetch ( wireMock . baseUri )
42+ . then ( async ( resp ) => {
43+ if ( resp . ok ) {
44+ return Promise . resolve ( wireMock ) ;
45+ } else {
46+ await new Promise ( resolve => setTimeout ( resolve , 1000 ) ) ;
47+ console . log ( `Retry connection to WireMock after wrong response status: ${ resp . status } ` ) ;
48+ return await waitForWiremockStarted ( wireMock ) ;
49+ }
50+ } )
51+ . catch ( async ( err ) => {
52+ await new Promise ( resolve => setTimeout ( resolve , 1000 ) ) ;
53+ console . log ( `Retry connection to WireMock after error: ${ err } ` ) ;
54+ return await waitForWiremockStarted ( wireMock ) ;
55+ } ) ;
56+ }
57+
58+ describe ( 'Wiremock test' , function ( ) {
59+ it ( 'Run Wiremock instance, wait, verify connection and shutdown' , async function ( ) {
60+ const wireMock = await runWireMockAsync ( ) ;
61+ try {
62+ assert . doesNotReject ( async ( ) => await wireMock . mappings . getAllMappings ( ) ) ;
63+ } finally {
64+ await wireMock . global . shutdown ( ) ;
65+ }
66+ } ) ;
67+ it ( 'Add mappings' , async function ( ) {
68+ const wireMock = await runWireMockAsync ( ) ;
69+ try {
70+ const requests = JSON . parse ( fs . readFileSync ( 'wiremock/mappings/test.json' , 'utf8' ) ) ;
71+ for ( const mapping of requests . mappings ) {
72+ await wireMock . mappings . createMapping ( mapping ) ;
73+ }
74+ const mappings = await wireMock . mappings . getAllMappings ( ) ;
75+ assert . strictEqual ( mappings . mappings . length , 2 ) ;
76+ const response = await axios . get ( 'http://localhost:8081/test/authorize.html' ) ;
77+ assert . strictEqual ( response . status , 200 ) ;
78+ } finally {
79+ await wireMock . global . shutdown ( ) ;
80+ }
81+ } ) ;
82+ } ) ;
83+
1084describe ( 'Oauth authentication' , function ( ) {
1185 let authTest ;
1286
@@ -45,8 +119,59 @@ describe('Oauth authentication', function () {
45119 } ) ;
46120} ) ;
47121
122+ describe ( 'Oauth PAT authentication' , function ( ) {
123+ let port ;
124+ let authTest ;
125+ let wireMock ;
126+ before ( async ( ) => {
127+ port = await getPortFree ( ) ;
128+ wireMock = await runWireMockAsync ( port ) ;
129+ } ) ;
130+ beforeEach ( async ( ) => {
131+ authTest = new AuthTest ( ) ;
132+ } ) ;
133+ afterEach ( async ( ) => {
134+ wireMock . scenarios . resetAllScenarios ( ) ;
135+ } ) ;
136+ after ( async ( ) => {
137+ await wireMock . global . shutdown ( ) ;
138+ } ) ;
139+
140+
141+ it ( 'Successful flow scenario PAT as token' , async function ( ) {
142+ await addWireMockMappingsFromFile ( 'wiremock/mappings/pat/successful_flow.json' ) ;
143+ const connectionOption = { ...connParameters . oauthPATOnWiremock , token : 'MOCK_TOKEN' , port : port } ;
144+ authTest . createConnection ( connectionOption ) ;
145+ await authTest . connectAsync ( ) ;
146+ authTest . verifyNoErrorWasThrown ( ) ;
147+ } ) ;
148+
149+ it ( 'Successful flow scenario PAT as password' , async function ( ) {
150+ await addWireMockMappingsFromFile ( 'wiremock/mappings/pat/successful_flow.json' ) ;
151+ const connectionOption = { ...connParameters . oauthPATOnWiremock , password : 'MOCK_TOKEN' , port : port } ;
152+ authTest . createConnection ( connectionOption ) ;
153+ await authTest . connectAsync ( ) ;
154+ authTest . verifyNoErrorWasThrown ( ) ;
155+ } ) ;
156+
157+ it ( 'Invalid token' , async function ( ) {
158+ await addWireMockMappingsFromFile ( 'wiremock/mappings/pat/invalid_pat_token.json' ) ;
159+ const connectionOption = { ...connParameters . oauthPATOnWiremock , token : 'INVALID_TOKEN' , port : port } ;
160+ authTest . createConnection ( connectionOption ) ;
161+ await authTest . connectAsync ( ) ;
162+ authTest . verifyErrorWasThrown ( 'Programmatic access token is invalid.' ) ;
163+ } ) ;
164+
165+ async function addWireMockMappingsFromFile ( filePath ) {
166+ const requests = JSON . parse ( fs . readFileSync ( filePath , 'utf8' ) ) ;
167+ for ( const mapping of requests . mappings ) {
168+ await wireMock . mappings . createMapping ( mapping ) ;
169+ }
170+ }
171+ } ) ;
172+
48173async function getToken ( ) {
49- const response = await axios . post ( snowflakeAuthTestOauthUrl , data , {
174+ const response = await axios . post ( snowflakeAuthTestOauthUrl , { } , {
50175 headers : {
51176 'Content-Type' : 'application/x-www-form-urlencoded;charset=UTF-8'
52177 } ,
@@ -59,9 +184,12 @@ async function getToken() {
59184 return response . data . access_token ;
60185}
61186
62- const data = [
63- `username=${ snowflakeAuthTestOktaUser } ` ,
64- `password=${ snowflakeAuthTestOktaPass } ` ,
65- 'grant_type=password' ,
66- `scope=session:role:${ snowflakeAuthTestRole . toLowerCase ( ) } `
67- ] . join ( '&' ) ;
187+ async function getPortFree ( ) {
188+ return new Promise ( res => {
189+ const srv = net . createServer ( ) ;
190+ srv . listen ( 0 , ( ) => {
191+ const port = srv . address ( ) . port ;
192+ srv . close ( ( err ) => res ( port ) ) ;
193+ } ) ;
194+ } ) ;
195+ }
0 commit comments