Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit319fd5b

Browse files
authored
chore: add e2e test against an external auth provider during workspace creation (#12985)
1 parent75223df commit319fd5b

File tree

4 files changed

+134
-21
lines changed

4 files changed

+134
-21
lines changed

‎site/e2e/helpers.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
typeResource,
3232
Response,
3333
typeRichParameter,
34+
typeExternalAuthProviderResource,
3435
}from"./provisionerGenerated";
3536

3637
// requiresEnterpriseLicense will skip the test if we're not running with an enterprise license
@@ -49,6 +50,7 @@ export const createWorkspace = async (
4950
templateName:string,
5051
richParameters:RichParameter[]=[],
5152
buildParameters:WorkspaceBuildParameter[]=[],
53+
useExternalAuthProvider:string|undefined=undefined,
5254
):Promise<string>=>{
5355
awaitpage.goto(`/templates/${templateName}/workspace`,{
5456
waitUntil:"domcontentloaded",
@@ -59,6 +61,25 @@ export const createWorkspace = async (
5961
awaitpage.getByLabel("name").fill(name);
6062

6163
awaitfillParameters(page,richParameters,buildParameters);
64+
65+
if(useExternalAuthProvider!==undefined){
66+
// Create a new context for the popup which will be created when clicking the button
67+
constpopupPromise=page.waitForEvent("popup");
68+
69+
// Find the "Login with <Provider>" button
70+
constexternalAuthLoginButton=page
71+
.getByRole("button")
72+
.getByText("Login with GitHub");
73+
awaitexpect(externalAuthLoginButton).toBeVisible();
74+
75+
// Click it
76+
awaitexternalAuthLoginButton.click();
77+
78+
// Wait for authentication to occur
79+
constpopup=awaitpopupPromise;
80+
awaitpopup.waitForSelector("text=You are now authenticated.");
81+
}
82+
6283
awaitpage.getByTestId("form-submit").click();
6384

6485
awaitexpectUrl(page).toHavePathName("/@admin/"+name);
@@ -648,6 +669,37 @@ export const echoResponsesWithParameters = (
648669
};
649670
};
650671

672+
exportconstechoResponsesWithExternalAuth=(
673+
providers:ExternalAuthProviderResource[],
674+
):EchoProvisionerResponses=>{
675+
return{
676+
parse:[
677+
{
678+
parse:{},
679+
},
680+
],
681+
plan:[
682+
{
683+
plan:{
684+
externalAuthProviders:providers,
685+
},
686+
},
687+
],
688+
apply:[
689+
{
690+
apply:{
691+
externalAuthProviders:providers,
692+
resources:[
693+
{
694+
name:"example",
695+
},
696+
],
697+
},
698+
},
699+
],
700+
};
701+
};
702+
651703
exportconstfillParameters=async(
652704
page:Page,
653705
richParameters:RichParameter[]=[],

‎site/e2e/hooks.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
importtype{Page}from"@playwright/test";
1+
importtype{BrowserContext,Page}from"@playwright/test";
2+
importhttpfrom"http";
3+
import{coderPort,gitAuth}from"./constants";
24

35
exportconstbeforeCoderTest=async(page:Page)=>{
46
// eslint-disable-next-line no-console -- Show everything that was printed with console.log()
@@ -45,6 +47,41 @@ export const beforeCoderTest = async (page: Page) => {
4547
});
4648
};
4749

50+
exportconstresetExternalAuthKey=async(context:BrowserContext)=>{
51+
// Find the session token so we can destroy the external auth link between tests, to ensure valid authentication happens each time.
52+
constcookies=awaitcontext.cookies();
53+
constsessionCookie=cookies.find((c)=>c.name==="coder_session_token");
54+
constoptions={
55+
method:"DELETE",
56+
hostname:"127.0.0.1",
57+
port:coderPort,
58+
path:`/api/v2/external-auth/${gitAuth.webProvider}?coder_session_token=${sessionCookie?.value}`,
59+
};
60+
61+
constreq=http.request(options,(res)=>{
62+
letdata="";
63+
res.on("data",(chunk)=>{
64+
data+=chunk;
65+
});
66+
67+
res.on("end",()=>{
68+
// Both 200 (key deleted successfully) and 500 (key was not found) are valid responses.
69+
if(res.statusCode!==200&&res.statusCode!==500){
70+
console.error("failed to delete external auth link",data);
71+
thrownewError(
72+
`failed to delete external auth link: HTTP response${res.statusCode}`,
73+
);
74+
}
75+
});
76+
});
77+
78+
req.on("error",(err)=>{
79+
throwerr.message;
80+
});
81+
82+
req.end();
83+
};
84+
4885
constisApiCall=(urlString:string):boolean=>{
4986
consturl=newURL(urlString);
5087
constapiPath="/api/v2";

‎site/e2e/playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export default defineConfig({
115115
// Tests for Deployment / User Authentication / OIDC
116116
CODER_OIDC_ISSUER_URL:"https://accounts.google.com",
117117
CODER_OIDC_EMAIL_DOMAIN:"coder.com",
118-
CODER_OIDC_CLIENT_ID:"1234567890",// FIXME: https://github.com/coder/coder/issues/12585
118+
CODER_OIDC_CLIENT_ID:"1234567890",
119119
CODER_OIDC_CLIENT_SECRET:"1234567890Secret",
120120
CODER_OIDC_ALLOW_SIGNUPS:"false",
121121
CODER_OIDC_SIGN_IN_TEXT:"Hello",

‎site/e2e/tests/externalAuth.spec.ts

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,37 @@ import type { Endpoints } from "@octokit/types";
22
import{test}from"@playwright/test";
33
importtype{ExternalAuthDevice}from"api/typesGenerated";
44
import{gitAuth}from"../constants";
5-
import{Awaiter,createServer}from"../helpers";
6-
import{beforeCoderTest}from"../hooks";
5+
import{
6+
Awaiter,
7+
createServer,
8+
createTemplate,
9+
createWorkspace,
10+
echoResponsesWithExternalAuth,
11+
}from"../helpers";
12+
import{beforeCoderTest,resetExternalAuthKey}from"../hooks";
13+
14+
test.beforeAll(async({ baseURL})=>{
15+
constsrv=awaitcreateServer(gitAuth.webPort);
16+
17+
// The GitHub validate endpoint returns the currently authenticated user!
18+
srv.use(gitAuth.validatePath,(req,res)=>{
19+
res.write(JSON.stringify(ghUser));
20+
res.end();
21+
});
22+
srv.use(gitAuth.tokenPath,(req,res)=>{
23+
constr=(Math.random()+1).toString(36).substring(7);
24+
res.write(JSON.stringify({access_token:r}));
25+
res.end();
26+
});
27+
srv.use(gitAuth.authPath,(req,res)=>{
28+
res.redirect(
29+
`${baseURL}/external-auth/${gitAuth.webProvider}/callback?code=1234&state=`+
30+
req.query.state,
31+
);
32+
});
33+
});
34+
35+
test.beforeEach(async({ context})=>resetExternalAuthKey(context));
736

837
test.beforeEach(({ page})=>beforeCoderTest(page));
938

@@ -57,30 +86,25 @@ test("external auth device", async ({ page }) => {
5786
awaitpage.waitForSelector("text=1 organization authorized");
5887
});
5988

60-
test("external auth web",async({ baseURL, page})=>{
61-
constsrv=awaitcreateServer(gitAuth.webPort);
62-
// The GitHub validate endpoint returns the currently authenticated user!
63-
srv.use(gitAuth.validatePath,(req,res)=>{
64-
res.write(JSON.stringify(ghUser));
65-
res.end();
66-
});
67-
srv.use(gitAuth.tokenPath,(req,res)=>{
68-
res.write(JSON.stringify({access_token:"hello-world"}));
69-
res.end();
70-
});
71-
srv.use(gitAuth.authPath,(req,res)=>{
72-
res.redirect(
73-
`${baseURL}/external-auth/${gitAuth.webProvider}/callback?code=1234&state=`+
74-
req.query.state,
75-
);
76-
});
89+
test("external auth web",async({ page})=>{
7790
awaitpage.goto(`/external-auth/${gitAuth.webProvider}`,{
7891
waitUntil:"domcontentloaded",
7992
});
8093
// This endpoint doesn't have the installations URL set intentionally!
8194
awaitpage.waitForSelector("text=You've authenticated with GitHub!");
8295
});
8396

97+
test("successful external auth from workspace",async({ page})=>{
98+
consttemplateName=awaitcreateTemplate(
99+
page,
100+
echoResponsesWithExternalAuth([
101+
{id:gitAuth.webProvider,optional:false},
102+
]),
103+
);
104+
105+
awaitcreateWorkspace(page,templateName,[],[],gitAuth.webProvider);
106+
});
107+
84108
constghUser:Endpoints["GET /user"]["response"]["data"]={
85109
login:"kylecarbs",
86110
id:7122116,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp