1+ import { randomUUID } from 'node:crypto' ;
12import { GenericContainer , StartedTestContainer , Wait } from 'testcontainers' ;
23import { ApiResponse , AuthToken , Authorizer } from '../lib' ;
34
4- const authorizerConfig = {
5+ jest . setTimeout ( 1200000 ) ; // Integration tests can be slow on CI (20 minutes)
6+
7+ const authorizerConfig : {
8+ authorizerURL : string ;
9+ redirectURL : string ;
10+ adminSecret : string ;
11+ clientID ?: string ;
12+ } = {
513 authorizerURL : 'http://localhost:8080' ,
614 redirectURL : 'http://localhost:8080/app' ,
7- // clientID: '3fab5e58-5693-46f2-8123-83db8133cd22',
815 adminSecret : 'secret' ,
916} ;
1017
@@ -18,38 +25,71 @@ const testConfig = {
1825 maginLinkLoginEmail : 'test_magic_link@test.com' ,
1926} ;
2027
21- // Using etheral.email for email sink: https://ethereal.email/create
22- const authorizerENV = {
23- ENV : 'production' ,
24- DATABASE_URL : 'data.db' ,
25- DATABASE_TYPE : 'sqlite' ,
26- CUSTOM_ACCESS_TOKEN_SCRIPT :
27- 'function(user,tokenPayload){var data = tokenPayload;data.extra = {\'x-extra-id\': user.id};return data;}' ,
28- DISABLE_PLAYGROUND : 'true' ,
29- SMTP_HOST : 'smtp.ethereal.email' ,
30- SMTP_PASSWORD : 'WncNxwVFqb6nBjKDQJ' ,
31- SMTP_USERNAME : 'sydnee.lesch77@ethereal.email' ,
32- LOG_LELVEL : 'debug' ,
33- SMTP_PORT : '587' ,
34- SENDER_EMAIL : 'test@authorizer.dev' ,
35- ADMIN_SECRET : 'secret' ,
36- } ;
28+ // Build v2 CLI args for authorizer (see authorizer/cmd/root.go). Using etheral.email for email sink.
29+ function buildAuthorizerCliArgs ( ) : { args : string [ ] ; clientId : string } {
30+ const clientId = randomUUID ( ) ;
31+ const clientSecret = randomUUID ( ) ;
32+ const jwtSecret = randomUUID ( ) ;
33+
34+ const args = [
35+ '--client-id' ,
36+ clientId ,
37+ '--client-secret' ,
38+ clientSecret ,
39+ '--jwt-type' ,
40+ 'HS256' ,
41+ '--jwt-secret' ,
42+ jwtSecret ,
43+ '--admin-secret' ,
44+ authorizerConfig . adminSecret ,
45+ '--env' ,
46+ 'production' ,
47+ '--database-type' ,
48+ 'sqlite' ,
49+ '--database-url' ,
50+ '/tmp/authorizer.db' ,
51+ '--enable-playground=false' ,
52+ '--log-level' ,
53+ 'debug' ,
54+ '--smtp-host' ,
55+ 'smtp.ethereal.email' ,
56+ '--smtp-port' ,
57+ '587' ,
58+ '--smtp-username' ,
59+ 'sydnee.lesch77@ethereal.email' ,
60+ '--smtp-password' ,
61+ 'WncNxwVFqb6nBjKDQJ' ,
62+ '--smtp-sender-email' ,
63+ 'test@authorizer.dev' ,
64+ '--enable-email-verification=true' ,
65+ '--enable-magic-link-login=true' ,
66+ ] ;
67+ return { args, clientId } ;
68+ }
3769
3870// const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
3971
4072const verificationRequests =
4173 'query {_verification_requests { verification_requests { id token email expires identifier } } }' ;
4274
4375describe ( 'Integration Tests - authorizer-js' , ( ) => {
44- let container : StartedTestContainer ;
76+ let container : StartedTestContainer | undefined ;
4577
4678 let authorizer : Authorizer ;
4779
4880 beforeAll ( async ( ) => {
49- container = await new GenericContainer ( 'lakhansamani/authorizer:latest' )
50- . withEnvironment ( authorizerENV )
81+ const { args, clientId } = buildAuthorizerCliArgs ( ) ;
82+
83+ container = await new GenericContainer ( 'lakhansamani/authorizer:2.0.0-rc.6' )
84+ . withCommand ( args )
5185 . withExposedPorts ( 8080 )
5286 . withWaitStrategy ( Wait . forHttp ( '/health' , 8080 ) . forStatusCode ( 200 ) )
87+ . withStartupTimeout ( 900000 ) // 15 minutes (CI can be slow)
88+ // Surface container stdout/stderr to help diagnose CI startup failures.
89+ . withLogConsumer ( ( chunk ) => {
90+ // Avoid changing log format; just mirror what container prints.
91+ process . stdout . write ( chunk . toString ( ) ) ;
92+ } )
5393 . start ( ) ;
5494
5595 authorizerConfig . authorizerURL = `http://${ container . getHost ( ) } :${ container . getMappedPort (
@@ -58,19 +98,13 @@ describe('Integration Tests - authorizer-js', () => {
5898 authorizerConfig . redirectURL = `http://${ container . getHost ( ) } :${ container . getMappedPort (
5999 8080 ,
60100 ) } /app`;
101+ authorizerConfig . clientID = clientId ;
61102 console . log ( 'Authorizer URL:' , authorizerConfig . authorizerURL ) ;
62103 authorizer = new Authorizer ( authorizerConfig ) ;
63- // get metadata
64- const metadataRes = await authorizer . getMetaData ( ) ;
65- // await sleep(50000);
66- expect ( metadataRes ?. data ) . toBeDefined ( ) ;
67- if ( metadataRes ?. data ?. client_id ) {
68- authorizer . config . clientID = metadataRes ?. data ?. client_id ;
69- }
70104 } ) ;
71105
72106 afterAll ( async ( ) => {
73- await container . stop ( ) ;
107+ if ( container ) await container . stop ( ) ;
74108 } ) ;
75109
76110 it ( 'should signup with email verification enabled' , async ( ) => {
@@ -101,10 +135,13 @@ describe('Integration Tests - authorizer-js', () => {
101135 ( i : { email : string } ) => i . email === testConfig . email ,
102136 ) ;
103137 expect ( item ) . not . toBeNull ( ) ;
138+ expect ( item ?. token ) . toBeDefined ( ) ;
104139
105140 const verifyEmailRes = await authorizer . verifyEmail ( { token : item . token } ) ;
106141 expect ( verifyEmailRes ?. data ) . toBeDefined ( ) ;
107142 expect ( verifyEmailRes ?. errors ) . toHaveLength ( 0 ) ;
143+ expect ( verifyEmailRes ?. data ?. access_token ) . toBeDefined ( ) ;
144+ expect ( verifyEmailRes ?. data ?. access_token ) . not . toBeNull ( ) ;
108145 expect ( verifyEmailRes ?. data ?. access_token ?. length ) . toBeGreaterThan ( 0 ) ;
109146 } ) ;
110147
@@ -117,13 +154,23 @@ describe('Integration Tests - authorizer-js', () => {
117154 } ) ;
118155 expect ( loginRes ?. data ) . toBeDefined ( ) ;
119156 expect ( loginRes ?. errors ) . toHaveLength ( 0 ) ;
120- expect ( loginRes ?. data ?. access_token . length ) . not . toEqual ( 0 ) ;
121- expect ( loginRes ?. data ?. refresh_token ?. length ) . not . toEqual ( 0 ) ;
122- expect ( loginRes ?. data ?. expires_in ) . not . toEqual ( 0 ) ;
123- expect ( loginRes ?. data ?. id_token . length ) . not . toEqual ( 0 ) ;
157+ expect ( loginRes ?. data ?. access_token ) . toBeDefined ( ) ;
158+ expect ( loginRes ?. data ?. access_token ) . not . toBeNull ( ) ;
159+ expect ( loginRes ?. data ?. access_token ?. length ) . toBeGreaterThan ( 0 ) ;
160+ expect ( loginRes ?. data ?. refresh_token ) . toBeDefined ( ) ;
161+ expect ( loginRes ?. data ?. refresh_token ) . not . toBeNull ( ) ;
162+ expect ( loginRes ?. data ?. refresh_token ?. length ) . toBeGreaterThan ( 0 ) ;
163+ expect ( loginRes ?. data ?. expires_in ) . toBeDefined ( ) ;
164+ expect ( loginRes ?. data ?. expires_in ) . not . toBeNull ( ) ;
165+ expect ( loginRes ?. data ?. expires_in ) . toBeGreaterThan ( 0 ) ;
166+ expect ( loginRes ?. data ?. id_token ) . toBeDefined ( ) ;
167+ expect ( loginRes ?. data ?. id_token ) . not . toBeNull ( ) ;
168+ expect ( loginRes ?. data ?. id_token ?. length ) . toBeGreaterThan ( 0 ) ;
124169 } ) ;
125170
126171 it ( 'should validate jwt token' , async ( ) => {
172+ expect ( loginRes ?. data ?. access_token ) . toBeDefined ( ) ;
173+ expect ( loginRes ?. data ?. access_token ) . not . toBeNull ( ) ;
127174 const validateRes = await authorizer . validateJWTToken ( {
128175 token_type : 'access_token' ,
129176 token : loginRes ?. data ?. access_token || '' ,
@@ -134,6 +181,8 @@ describe('Integration Tests - authorizer-js', () => {
134181 } ) ;
135182
136183 it ( 'should update profile successfully' , async ( ) => {
184+ expect ( loginRes ?. data ?. access_token ) . toBeDefined ( ) ;
185+ expect ( loginRes ?. data ?. access_token ) . not . toBeNull ( ) ;
137186 const updateProfileRes = await authorizer . updateProfile (
138187 {
139188 given_name : 'bob' ,
@@ -147,28 +196,36 @@ describe('Integration Tests - authorizer-js', () => {
147196 } ) ;
148197
149198 it ( 'should fetch profile successfully' , async ( ) => {
199+ expect ( loginRes ?. data ?. access_token ) . toBeDefined ( ) ;
200+ expect ( loginRes ?. data ?. access_token ) . not . toBeNull ( ) ;
150201 const profileRes = await authorizer . getProfile ( {
151202 Authorization : `Bearer ${ loginRes ?. data ?. access_token } ` ,
152203 } ) ;
153204 expect ( profileRes ?. data ) . toBeDefined ( ) ;
154205 expect ( profileRes ?. errors ) . toHaveLength ( 0 ) ;
206+ expect ( profileRes ?. data ?. given_name ) . toBeDefined ( ) ;
155207 expect ( profileRes ?. data ?. given_name ) . toMatch ( 'bob' ) ;
156208 } ) ;
157209
158210 it ( 'should get access_token using refresh_token' , async ( ) => {
211+ expect ( loginRes ?. data ?. refresh_token ) . toBeDefined ( ) ;
212+ expect ( loginRes ?. data ?. refresh_token ) . not . toBeNull ( ) ;
159213 const tokenRes = await authorizer . getToken ( {
160214 grant_type : 'refresh_token' ,
161- refresh_token : loginRes ?. data ?. refresh_token ,
215+ refresh_token : loginRes ?. data ?. refresh_token || '' ,
162216 } ) ;
163217 expect ( tokenRes ?. data ) . toBeDefined ( ) ;
164218 expect ( tokenRes ?. errors ) . toHaveLength ( 0 ) ;
165- expect ( tokenRes ?. data ?. access_token . length ) . not . toEqual ( 0 ) ;
219+ expect ( tokenRes ?. data ?. access_token ) . toBeDefined ( ) ;
220+ expect ( tokenRes ?. data ?. access_token ?. length ) . toBeGreaterThan ( 0 ) ;
166221 if ( loginRes && loginRes . data ) {
167222 loginRes . data . access_token = tokenRes ?. data ?. access_token || '' ;
168223 }
169224 } ) ;
170225
171226 it ( 'should deactivate account' , async ( ) => {
227+ expect ( loginRes ?. data ?. access_token ) . toBeDefined ( ) ;
228+ expect ( loginRes ?. data ?. access_token ) . not . toBeNull ( ) ;
172229 const deactivateRes = await authorizer . deactivateAccount ( {
173230 Authorization : `Bearer ${ loginRes ?. data ?. access_token } ` ,
174231 } ) ;
@@ -177,11 +234,13 @@ describe('Integration Tests - authorizer-js', () => {
177234 } ) ;
178235
179236 it ( 'should throw error while accessing profile after deactivation' , async ( ) => {
237+ expect ( loginRes ?. data ?. access_token ) . toBeDefined ( ) ;
180238 const resp = await authorizer . getProfile ( {
181239 Authorization : `Bearer ${ loginRes ?. data ?. access_token } ` ,
182240 } ) ;
183241 expect ( resp ?. data ) . toBeUndefined ( ) ;
184- expect ( resp ?. errors ) . toHaveLength ( 1 ) ;
242+ expect ( resp ?. errors ) . toBeDefined ( ) ;
243+ expect ( resp ?. errors . length ) . toBeGreaterThan ( 0 ) ;
185244 } ) ;
186245
187246 describe ( 'magic link login' , ( ) => {
@@ -195,22 +254,28 @@ describe('Integration Tests - authorizer-js', () => {
195254 it ( 'should verify email' , async ( ) => {
196255 const verificationRequestsRes = await authorizer . graphqlQuery ( {
197256 query : verificationRequests ,
257+ variables : { } ,
198258 headers : {
199259 'x-authorizer-admin-secret' : authorizerConfig . adminSecret ,
200260 } ,
201261 } ) ;
202262 const requests =
203263 verificationRequestsRes ?. data ?. _verification_requests
204264 . verification_requests ;
265+ expect ( verificationRequestsRes ?. data ) . toBeDefined ( ) ;
266+ expect ( verificationRequestsRes ?. errors ) . toHaveLength ( 0 ) ;
205267 const item = requests . find (
206268 ( i : { email : string } ) => i . email === testConfig . maginLinkLoginEmail ,
207269 ) ;
208270 expect ( item ) . not . toBeNull ( ) ;
271+ expect ( item ?. token ) . toBeDefined ( ) ;
209272 const verifyEmailRes = await authorizer . verifyEmail ( {
210273 token : item . token ,
211274 } ) ;
212275 expect ( verifyEmailRes ?. data ) . toBeDefined ( ) ;
213276 expect ( verifyEmailRes ?. errors ) . toHaveLength ( 0 ) ;
277+ expect ( verifyEmailRes ?. data ?. user ) . toBeDefined ( ) ;
278+ expect ( verifyEmailRes ?. data ?. user ?. signup_methods ) . toBeDefined ( ) ;
214279 expect ( verifyEmailRes ?. data ?. user ?. signup_methods ) . toContain (
215280 'magic_link_login' ,
216281 ) ;
0 commit comments