diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56e500a..25bddf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,8 +80,11 @@ jobs: CI: true NEXT_TELEMETRY_DISABLED: 1 NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} + CYPRESS_NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} CYPRESS_TEST_USER_ID: ${{ secrets.CYPRESS_TEST_USER_ID }} CYPRESS_TEST_USER_PW: ${{ secrets.CYPRESS_TEST_USER_PW }} + CYPRESS_TEST_USER_NUMBER: ${{ secrets.CYPRESS_TEST_USER_NUMBER }} + CYPRESS_TEST_UNIVERSITY_NAME: ${{ secrets.TEST_UNIVERSITY_NAME }} - name: "========== πŸ§ͺ AllClass E2E β€’ END ==========" if: always() diff --git a/app/layout.tsx b/app/layout.tsx index 7f290d2..14b8884 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -15,6 +15,7 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { + metadataBase: new URL('https://allclass.vercel.app'), title: { default: 'AllClass - λΆ€μ‚°μ†Œμ† λŒ€ν•™κ΅ κ°•μ˜μ •λ³΄ ν”Œλž«νΌ', template: '%s | AllClass', diff --git a/app/sitemap.ts b/app/sitemap.ts index f056e08..1be0126 100644 --- a/app/sitemap.ts +++ b/app/sitemap.ts @@ -1,44 +1,24 @@ import { MetadataRoute } from 'next'; import { universityNames } from '@/constants'; -import { getLectureListStatic } from '@/lib/lecture'; -export default async function sitemap(): Promise { - const baseUrl = 'https://all-class.vercel.app'; +export default function sitemap(): MetadataRoute.Sitemap { + const baseUrl = 'https://allclass.vercel.app'; - const staticPages = [ + const staticPages: MetadataRoute.Sitemap = [ { url: baseUrl, lastModified: new Date(), - changeFrequency: 'daily' as const, + changeFrequency: 'daily', priority: 1, }, ]; - const universityPages = universityNames.map((universityName) => ({ + const universityPages: MetadataRoute.Sitemap = universityNames.map((universityName) => ({ url: `${baseUrl}/${encodeURIComponent(universityName)}`, lastModified: new Date(), - changeFrequency: 'daily' as const, + changeFrequency: 'daily', priority: 0.8, })); - const lecturePages: MetadataRoute.Sitemap = []; - - for (const universityName of universityNames) { - try { - const lectures = await getLectureListStatic(universityName); - if (lectures.success && lectures.lectures) { - const pages = lectures.lectures.map((lecture) => ({ - url: `${baseUrl}/${encodeURIComponent(universityName)}/${lecture.lectureId}`, - lastModified: new Date(), - changeFrequency: 'weekly' as const, - priority: 0.7, - })); - lecturePages.push(...pages); - } - } catch (error) { - console.error(`Error generating sitemap for ${universityName}:`, error); - } - } - - return [...staticPages, ...universityPages, ...lecturePages]; + return [...staticPages, ...universityPages]; } diff --git a/cypress/e2e/tier1-critical/01-auth-and-review.cy.ts b/cypress/e2e/tier1-critical/01-auth-and-review.cy.ts index e3a4d6d..004380b 100644 --- a/cypress/e2e/tier1-critical/01-auth-and-review.cy.ts +++ b/cypress/e2e/tier1-critical/01-auth-and-review.cy.ts @@ -11,7 +11,17 @@ describe('μ‚¬μš©μžλŠ” λ‘œκ·ΈμΈμ„ν•˜κ³  μžμ‹ μ΄ 듀은 κ°•μ˜μ— 리뷰λ₯Ό cy.uiLogin(); cy.getMyLectures().then((response) => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions expect(response.status).to.eq(200); + + cy.then(() => console.log('getMyLectures response:', response.body)); + + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(response.body.data).to.not.be.null; + + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(response.body.data).to.be.an('array'); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions expect(response.body.data).to.have.length.greaterThan(0); const enrolledLecture = response.body.data[0]; @@ -47,6 +57,12 @@ describe('μ‚¬μš©μžλŠ” λ‘œκ·ΈμΈμ„ν•˜κ³  μžμ‹ μ΄ 듀은 κ°•μ˜μ— 리뷰λ₯Ό cy.uiLogin(); cy.getMyLectures().then((enrolledResponse) => { + cy.then(() => console.log('getMyLectures response:', enrolledResponse.body)); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(enrolledResponse.body.data).to.not.be.null; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(enrolledResponse.body.data).to.be.an('array'); + const enrolledLectures = enrolledResponse.body.data.map( (lecture: { lectureName: string }) => lecture.lectureName ); diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 1d87680..f96cc52 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -49,17 +49,32 @@ Cypress.Commands.add('uiLogin', (userId?: string, userPw?: string) => { }); Cypress.Commands.add('getMyLectures', () => { + const apiUrl = Cypress.env('NEXT_PUBLIC_API_URL') || Cypress.env('CYPRESS_NEXT_PUBLIC_API_URL'); + if (!apiUrl) { + throw new Error('NEXT_PUBLIC_API_URL ν™˜κ²½λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€'); + } + + const userNumber = Cypress.env('TEST_USER_NUMBER') || Cypress.env('CYPRESS_TEST_USER_NUMBER'); + + cy.log(`API URL: ${apiUrl}`); + cy.log(`User Number: ${userNumber}`); + return cy.request({ method: 'GET', - url: `${Cypress.env('NEXT_PUBLIC_API_URL')}/class/me`, - qs: { userNumber: Cypress.env('TEST_USER_NUMBER') }, + url: `${apiUrl}/class/me`, + qs: { userNumber }, }); }); Cypress.Commands.add('getUniversityLectures', (universityName: string) => { + const apiUrl = Cypress.env('NEXT_PUBLIC_API_URL') || Cypress.env('CYPRESS_NEXT_PUBLIC_API_URL'); + if (!apiUrl) { + throw new Error('NEXT_PUBLIC_API_URL ν™˜κ²½λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€'); + } + return cy.request({ method: 'GET', - url: `${Cypress.env('NEXT_PUBLIC_API_URL')}/class`, + url: `${apiUrl}/class`, qs: { university: universityName }, }); }); @@ -82,7 +97,6 @@ Cypress.Commands.add('getLectureWithReviews', (universityName: string) => { return cy.getUniversityLectures(universityName).then((response) => { const lectures = response.body.data as { lectureName: string; lectureId: number }[]; - // 각 κ°•μ˜λ₯Ό 순차적으둜 ν™•μΈν•˜μ—¬ 리뷰가 μžˆλŠ” 첫 번째 κ°•μ˜ μ°ΎκΈ° let currentIndex = 0; const checkNextLecture = (): Cypress.Chainable<{ lectureName: string; lectureId: number }> => { @@ -92,10 +106,16 @@ Cypress.Commands.add('getLectureWithReviews', (universityName: string) => { const lecture = lectures[currentIndex]; + const apiUrl = + Cypress.env('NEXT_PUBLIC_API_URL') || Cypress.env('CYPRESS_NEXT_PUBLIC_API_URL'); + if (!apiUrl) { + throw new Error('NEXT_PUBLIC_API_URL ν™˜κ²½λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€'); + } + return cy .request({ method: 'GET', - url: `${Cypress.env('NEXT_PUBLIC_API_URL')}/class`, + url: `${apiUrl}/class`, qs: { university: universityName, lectureId: lecture.lectureId,