feat: refine navigation and account access flow
This commit is contained in:
+59
-4
@@ -69,18 +69,30 @@ test('관리자는 이메일만으로 Google 로그인 허용 계정을 관리
|
||||
url: '/',
|
||||
headers: { cookie: adminCookie },
|
||||
});
|
||||
assert.match(pageResponse.body, /id="access-menu-button"/);
|
||||
assert.match(pageResponse.body, /id="access-drawer"/);
|
||||
assert.match(pageResponse.body, /id="drawer-logout"/);
|
||||
assert.match(pageResponse.body, /id="site-header"/);
|
||||
assert.match(pageResponse.body, /id="access-overlay"/);
|
||||
assert.match(pageResponse.body, /id="scroll-to-top"/);
|
||||
|
||||
const appBarResponse = await app.inject({ method: 'GET', url: '/js/app-bar.js' });
|
||||
assert.equal(appBarResponse.statusCode, 200);
|
||||
assert.match(appBarResponse.body, /id="access-menu-button"/);
|
||||
assert.match(appBarResponse.body, /id="access-drawer"/);
|
||||
assert.match(appBarResponse.body, /id="drawer-logout"/);
|
||||
|
||||
const memberPageResponse = await app.inject({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
headers: { cookie: authCookie(app, 'google-user-2') },
|
||||
});
|
||||
assert.match(memberPageResponse.body, /aria-label="메뉴 열기"/);
|
||||
assert.match(memberPageResponse.body, /id="site-header"/);
|
||||
|
||||
const detailPageResponse = await app.inject({
|
||||
method: 'GET',
|
||||
url: '/recipe/recipe-1',
|
||||
headers: { cookie: adminCookie },
|
||||
});
|
||||
assert.match(detailPageResponse.body, /id="site-header"/);
|
||||
assert.doesNotMatch(detailPageResponse.body, /id="logout-button"/);
|
||||
|
||||
const addResponse = await app.inject({
|
||||
method: 'POST',
|
||||
@@ -152,6 +164,8 @@ test('인증 cookie가 없으면 API를 거부하고 페이지는 로그인으
|
||||
const loginResponse = await app.inject({ method: 'GET', url: '/login' });
|
||||
assert.equal(loginResponse.statusCode, 200);
|
||||
assert.match(loginResponse.body, /Our Recipe Atlas/);
|
||||
assert.match(loginResponse.body, /id="login-alert"/);
|
||||
assert.match(loginResponse.body, /src="\/js\/login.js"/);
|
||||
|
||||
const cssResponse = await app.inject({ method: 'GET', url: '/css/app.css' });
|
||||
assert.equal(cssResponse.statusCode, 200);
|
||||
@@ -209,6 +223,47 @@ test('Google 로그인 시작 경로는 PKCE S256 authorization 요청을 만든
|
||||
assert.equal(location.hostname, 'accounts.google.com');
|
||||
assert.equal(location.searchParams.get('code_challenge_method'), 'S256');
|
||||
assert.equal(location.searchParams.get('scope'), 'openid email profile');
|
||||
|
||||
const selectAccountResponse = await app.inject({
|
||||
method: 'GET',
|
||||
url: '/auth/google/select-account',
|
||||
});
|
||||
const selectAccountLocation = new URL(selectAccountResponse.headers.location);
|
||||
assert.equal(selectAccountLocation.searchParams.get('prompt'), 'select_account');
|
||||
});
|
||||
|
||||
test('허용되지 않은 Google 계정은 안내 UI가 있는 로그인 페이지로 보낸다', async (t) => {
|
||||
const dependencies = createDependencies(new FakeRecipeRepository());
|
||||
dependencies.googleClient = {
|
||||
async verifyIdToken() {
|
||||
return {
|
||||
getPayload: () => ({
|
||||
sub: 'not-allowed-user',
|
||||
email: 'not-allowed@example.com',
|
||||
email_verified: true,
|
||||
}),
|
||||
};
|
||||
},
|
||||
};
|
||||
const app = await buildApp({
|
||||
config: createTestConfig({
|
||||
google: {
|
||||
clientId: 'google-client-id',
|
||||
clientSecret: 'google-client-secret',
|
||||
callbackUrl: 'http://localhost:3000/auth/google/callback',
|
||||
allowedEmails: new Set(['allowed@example.com']),
|
||||
},
|
||||
}),
|
||||
dependencies,
|
||||
});
|
||||
t.after(() => app.close());
|
||||
app.googleOAuth2.getAccessTokenFromAuthorizationCodeFlow = async () => ({
|
||||
token: { id_token: 'test-id-token' },
|
||||
});
|
||||
|
||||
const response = await app.inject({ method: 'GET', url: '/auth/google/callback' });
|
||||
assert.equal(response.statusCode, 302);
|
||||
assert.equal(response.headers.location, '/login?error=account-not-allowed');
|
||||
});
|
||||
|
||||
test('import preview와 소유자별 Recipe CRUD가 이어진다', async (t) => {
|
||||
|
||||
Reference in New Issue
Block a user