CodeGym /Kurslar /ChatGPT Apps /İlk smoke testi: “Hello widget” və openExternal

İlk smoke testi: “Hello widget” və openExternal

ChatGPT Apps
Səviyyə , Dərs
Mövcuddur

1. ChatGPT App üçün smoke test nədir

Adi veb‑inkişaf dünyasında smoke test — bu, “sistem ümumiyyətlə işləyirmi?” sualına minimal yoxlamadır. Səhifə açılır, düymələr çökmür, kritik heç nə “yanmır”.

ChatGPT Apps dünyasında smoke test bir qədər maraqlıdır, çünki zəncirdə birdən çox həlqə iştirak edir:

  1. Vidcetinizin kodu (React/Next.js).
  2. Next.js dev serveri.
  3. Tunel (ngrok/Cloudflare).
  4. iframe yaradan və vidcetinizi söhbətin içinə yükləyən ChatGPT.

Bizim üçün yaxşı smoke test — bu vəziyyətdir ki:

  • vidcet ChatGPT daxilində xətasız render olunur;
  • əsas interaktivlik işləyir (məsələn, düyməni sıxdınız — xarici keçid açıldı);
  • nə brauzer konsolunda, nə də dev serverin loglarında qırmızı səhv seli yoxdur.

Vacibdir: bu mərhələdə hələ MCP alətlərini yoxlamırıq, yük testləri etmirik və token xərclərini saymırıq. Tapşırığımız təvazökar və praktikdir: “kod → Next.js → tunel → ChatGPT → istifadəçi” zəncirinin ümumiyyətlə bağlandığını sübut etmək.

Bunu zehində belə bir cədvəl kimi təsəvvür etmək rahatdır:

Nəyi yoxlayırıq Necə başa düşək ki, hər şey qaydasındadır
Vidcetin render olunması ChatGPT‑də “pozulmuş iframe” deyil, bizim UI görünür
ChatGPT ↔ serverimiz arasında əlaqə “tətbiqi yükləyə bilmirəm” tipli xətalar yoxdur
Sandbox‑da JS‑in işi onClick handler‑ləri doğrudan icra olunur
Xarici keçidi açmaq imkanı Düymə göstərilən URL ilə yeni tab/pəncərə açır

2. Tədris App-ımız: sadə “Hello GiftGenius”

Bu kursda biz tədricən hədiyyə seçimi üzrə köməkçi olan GiftGenius tətbiqini qururuq. Bu addımda hələ heç nə seçmir, amma heç olmasa nəzakətlə salam verə və “daha ətraflı öyrən” keçidini göstərə bilər.

Bizə minimal, amma səmimi bir vidcet lazımdır: mürəkkəb məntiqsiz, lakin canlı React kodu ilə.

Vidcet komponentinin ən sadə variantı belə görünə bilər (adı və stilləri özünüzə uyğunlaşdıra bilərsiniz, amma kurs planındakı bazanı götürək):


// app/widget/page.tsx
'use client';

export default function GiftGeniusWidget() {
  return (
    <main style={{ padding: 16, fontFamily: 'system-ui, sans-serif' }}>
      <h1 style={{ fontSize: 24, marginBottom: 8 }}>
        Hello from GiftGenius
      </h1>
      <p style={{ marginBottom: 16 }}>
        Bu sizin ilk ChatGPT App-inizdir. Sonra ona hədiyyə seçməyi öyrədəcəyik.
      </p>
    </main>
  );
}

Bir neçə vacib məqam.

Əvvəla, faylın əvvəlindəki 'use client'; direktivi komponenti kliyen tərəfli edir. Onsuz Next.js faylı server komponenti kimi qəbul edəcək və siz window, onClick handler‑ləri və ümumiyyətlə istənilən brauzer API‑sindən istifadə edə bilməyəcəksiniz.

İkincisi, bu adi bir React komponentidir. Burada “Apps SDK möcüzəsi” görünmür — və bu düzdür. Onun ChatGPT daxilində peyda olmasının bütün sehrləri MCP serverinin konfiqurasiyasında və vidcet URL‑ini qaytaran alətdə gizlənib. Bununla sonra məşğul olacağıq, indi isə bizi yalnız UI maraqlandırır.

3. Vidceti şablona yerləşdiririk və işə salırıq

Apps SDK üçün rəsmi Next.js şablonunda vidcet səhifəsi adətən artıq olur; siz ya onu redaktə edirsiniz, ya da lazım olan marşrut üçün (məsələn, /widget) öz səhifənizi yaradırsınız.

Tutaq ki, sizdə elə app/widget/page.tsx var və məzmununu yuxarıdakı kodla əvəz edirsiniz. Sonra zəncir belə görünür:

  1. Faylı yadda saxlayırsınız.
  2. Next.js‑in dev serveri (npm run dev ilə artıq işə salınıb) lazım olan modulları yenidən yükləyir, HMR səhifəni yeniləyir.
  3. Tunel vasitəsilə sizin publik HTTPS URL eyni /widget yolunda yenilənmiş UI‑ni qaytarmağa başlayır.

Bunu iki üsulla yoxlamaq olar.

Əvvəlcə köhnə qayda ilə — lokal brauzerdə. Açırsınız:

http://localhost:3000/widget

və eyni Hello from GiftGenius görürsünüz. Bəli, bu hələ ChatGPT deyil, sadəcə Next.js tətbiqinizin UI‑sinin işlək olduğuna əmin olursunuz.

Sonra — tunel vasitəsilə. Verilən URL‑i (məsələn, https://witty-cat.ngrok-free.app) götürür, sonuna /widget əlavə edir və adi brauzerdə açırsınız:

https://witty-cat.ngrok-free.app/widget

Hər şey qaydasındadırsa, səhifə eyni görünməlidir. Deməli, “Next.js → tunel → sizin brauzeriniz” zənciri işləyir, indi onların arasına ChatGPT‑ni daxil etmək qalır.

4. Vidceti ChatGPT daxilində yoxlayırıq

Dev Mode‑da ChatGPT, əslində, üç addım edir: iframe yaradır, onun src‑ni sizin publik URL‑inizə qoyur və bu iframe‑ə çat mesajı daxilində yaşamağa icazə verir.

Sadələşdirilmiş şəkildə hadisə belə görünür:

sequenceDiagram
    participant Dev as Siz (Dev)
    participant Next as Next.js dev server
    participant Tun as Tunel (HTTPS)
    participant GPT as ChatGPT
    participant User as İstifadəçi

    Dev->>Next: npm run dev (http://localhost:3000)
    Dev->>Tun: Tunelın 3000 portuna işə salınması
    GPT->>Tun: GET https://.../widget
    Tun->>Next: http://localhost:3000/widget ünvanına proksi
    Next-->>Tun: Vidcetin HTML + JS-i
    Tun-->>GPT: HTML/JS ilə cavab
    GPT->>User: Vidcetli iframe-in renderi

Nəticəni görmək üçün siz:

  1. ChatGPT‑ni brauzerdə açır, lazım olan modeli seçirsiniz (adətən GPT‑5.1 və ya Dev Mode üçün susmaya görə təyin olunmuş model).
  2. Tətbiqinizi açıq şəkildə seçirsiniz (Apps/Developer menyusu ilə) və ya belə bir ifadə ilə “çağırırsınız”: “GiftGenius tətbiqini işə sal”.
  3. ChatGPT sizin App‑i çağırır, MCP server cavab qaytarır, UI‑a linki (elə həmin /widget) daxil edir və çat mesajında vidcetiniz peyda olur.

Hər şey qaydasındadırsa, elə ChatGPT daxilində tanış “Hello from GiftGenius” başlığını görəcəksiniz. Bu mərhələdə smoke test demək olar ki, keçilib: iframe render olunur, “Next.js → tunel → ChatGPT” zənciri işləyir. Cədvəldən son məqam qaldı — vidcet xarici keçidi proqnozlaşdırılan şəkildə aça bilir. Bunun üçün bizə openExternal lazım olacaq.

Bir az sonra kodu dəyişməyə başlayanda normal dev dövrü təxminən belə görünəcək:

  1. JSX‑i dəyişirsiniz.
  2. Yadda saxlayırsınız.
  3. Ya ChatGPT vərəqini yeniləyirsiniz, ya da (bəzən) vidceti “tərpətmək” kifayətdir — məsələn, yeni mesaj göndərmək və ya App‑i yenidən işə salmaq (şablonunuzun və keşləmənin necə qurulmasından asılı olaraq).

Dəyişikliklər görünmürsə, ilk növbədə üç şübhəlini düşünün: dev server işləmir, tunel qopub və ya ChatGPT köhnə URL‑ə qoşulub. “Nələrsə alınmadıqda xətaları harada axtarmaq lazımdır” bölməsində bu ssenarini daha ətraflı müzakirə edəcəyik.

5. Niyə sadəcə <a href> qoyub unutmaq olmaz

Smoke testimizin son bəndini — xarici səhifəni açan düyməni — yerinə yetirmək üçün openExternal ilə tanış olacağıq. Məntiqli sual: “Ümumiyyətlə niyə bu openExternal? Niyə adi keçid etməyək?”

Məsələ ondadır ki, vidcetiniz “sadəcə brauzerdə” yox, ChatGPT idarə etdiyi iframe daxilində yaşayır. Bu iframe kifayət qədər sərt sandboxda işləyir: Content Security Policy məhdudiyyətləri, sandbox atributları, target="_blank" ilə qəribəliklər və popup bloklanması tətbiq oluna bilər. Nəticədə <ahref="…"> və ya window.open() davranışı bu cür iframe daxilində proqnozlaşdırılmayan ola bilər: tam ignorlamadan tutmuş, kodunuzun nəzarət etmədiyi xəbərdarlıqlara qədər.

Bundan əlavə, UX baxımından OpenAI sizin nə vaxt və necə xarici səhifələr açdığınızı idarə etmək istəyir. Buna görə də Apps SDK vahid körpü təqdim edir — window.openai: kodunuz birbaşa parent pəncərəyə girmir, əməliyyatı aydın təsvir olunmuş API ilə host tətbiqə delegasiya edir.

6. API window.openai.openExternal: bu nədir və necə işləyir

Vidcet sandboxunda qlobal window.openai obyektinə çıxış var. Bu, UI‑nızla ChatGPT arasında əsas “körpü”dür: onun vasitəsilə alətləri çağırmaq, follow‑up mesajlar göndərmək, göstərim rejimini dəyişmək, vidcet vəziyyətini idarə etmək və əlbəttə, xarici keçidlər açmaq mümkündür.

Bu mühazirədə bizi konkret bir metod maraqlandırır:

window.openai.openExternal({ href: string }): void;

window.openai.openExternal({ href: 'https://example.com' }) çağırdığınızda, ChatGPT:

  1. URL‑in siyasətlərə uyğun olduğunu yoxlayır.
  2. İstifadəçiyə xəbərdarlıq göstərə bilər (məsələn, bunun xarici sayt olduğunu).
  3. Keçidi istifadəçinin brauzerində yeni tab/pəncərədə açır.

İki şeyi başa düşmək vacibdir.

Əvvəla, bu tamamilə kliyen tərəfli əməliyyatdır. MCP alətlərini çağırmır, backend‑inizə getmir və OpenAI tokenləri sərf etmir. Bu, sadəcə host tətbiqə “xahiş edirik, bu URL‑i aç” siqnalıdır.

İkincisi, bu üsul sandboxla uyğundur. ChatGPT keçidin dəqiq necə açılacağına özü qərar verir və iframe‑inizə window.open() ilə həddən artıq davranmağa imkan vermir.

7. Vidcetimizə openExternal ilə düymə əlavə edirik

İndi “Hello GiftGenius”‑dən xarici keçid açmağı öyrənək. Ən sadə ssenari: “Demo keçidini aç” düyməsi, məsələn, sənədləşməyə və ya servisin sizin landing səhifəsinə aparır.

Əvvəlcə kiçik bir helper yazaq ki, TypeScript irad tutmasın və vidcet təsadüfən /widget yolunu brauzerdə birbaşa açsanız (harada ki, window.openai hələ yoxdur) çökməsin:

// app/widget/openExternalSafe.ts
export function openExternalSafe(href: string) {
  if (typeof window !== 'undefined' && (window as any).openai?.openExternal) {
    (window as any).openai.openExternal({ href });
  } else {
    // ChatGPT olmadan lokal baxış üçün fallback
    window.open(href, '_blank', 'noopener,noreferrer');
  }
}

Burada mən qəsdən (window as any) istifadə edirəm ki, window.openai‑ın tipizasiyası ilə sizi yükləməyim. Kursun bir qədər sonra bu obyektin interfeysini səliqə ilə təsvir edəcəyik. Hələlik kodun kompilyasiya olub işləməsi kifayətdir.

İndi helper‑i vidcetimizdə qoşaq və düymə əlavə edək:

// app/widget/page.tsx
'use client';

import { openExternalSafe } from './openExternalSafe';

export default function GiftGeniusWidget() {
  return (
    <main style={{ padding: 16, fontFamily: 'system-ui, sans-serif' }}>
      <h1 style={{ fontSize: 24, marginBottom: 8 }}>
        Hello from GiftGenius
      </h1>
      <p style={{ marginBottom: 16 }}>
        Bu sizin ilk ChatGPT App-inizdir. Sonra ona hədiyyə seçməyi öyrədəcəyik.
      </p>
      <button
        type="button"
        onClick={() => openExternalSafe('https://example.com')}
        style={{
          padding: '8px 16px',
          borderRadius: 8,
          border: '1px solid #ccc',
          cursor: 'pointer',
        }}
      >
        Demo keçidini aç
      </button>
    </main>
  );
}

Nə baş verəcək klik edəndə.

Vidcet ChatGPT daxilində işə salınıbsa, window.openai.openExternal mövcuddur və ChatGPT https://example.com ünvanını qaydalara uyğun açacaq.

Əgər http://localhost:3000/widget səhifəsini adi brauzerdə açmısınızsa, window.openai yoxdur və fallback işləyəcək: brauzerin adi vasitələri ilə yeni tab açılacaq. Burada window.open yalnız /widget‑i adi brauzerdə birbaşa açdığınız kontekstdə istifadə olunur, yəni artıq ChatGPT sandboxu daxilində deyilsiniz. Bu kontekstdə o, adi qaydada işləyir və problem yaratmır.

openExternal‑i daha ətraflı 3‑cü modulda (vidcet və sandbox haqqında ayrıca mühazirə) müzakirə edəcəyik, ona görə indi rahatlıqla tətbiqi işə salmağa keçə bilərsiniz.

8. Mini end‑to‑end smoke test

İndi tam miqyaslı “döyüş” sınağı edə bilərik. Bütün addımlardan keçməyə çalışın:

  1. Dev serverin işə salındığına əmin olun (npm run dev) və http://localhost:3000/widget ünvanında Hello from GiftGenius gördüyünüzü yoxlayın.
  2. 3000 portuna tunelin qaldırıldığına və publik URL‑in xarici brauzerdən açıldığına əmin olun.
  3. ChatGPT‑ni açın, Dev Mode‑u aktivləşdirin və App‑inizin düzgün URL‑ə qoşulduğuna əmin olun (publik, localhost deyil).
  4. Çatı açın, App‑i seçin (və ya modeldən onu işə salmağı xahiş edin).
  5. Daxili vidcetdə “Hello from GiftGenius” göründüyünə əmin olun.
  6. “Demo keçidini aç” düyməsini klikləyin və brauzerdə https://example.com (və ya sizin ünvanınız) açıldığına əmin olun.

Bütün bunlar işləyibsə, deməli:

  • Vidcetin HTML/JS‑i düzgün toplanır və Next server tərəfindən verilir.
  • HTTPS tunel sorğuları düzgün proksi edir.
  • ChatGPT URL‑inizə etibar edir və vidceti yükləyə bilir.
  • window.openai işləyir və xarici keçidin açılması komandasını ötürür.

Bu, ilk smoke testdən gözlədiyimiz şeydir.

9. Nələrsə alınmadıqda xətaları harada axtarmaq lazımdır

“Adi” frontenddən fərqli olaraq, burada diaqnostika üçün cəmi üç əsas yeriniz var. Hansında nəyin qırıldığını tez anlamaq vacibdir:

  1. Əvvəlcə ChatGPT‑dəki UI‑a baxın. Vidcet əvəzinə “Error loading app” və ya “We had trouble talking to your app” kimi bir səhv mesajı görürsünüzsə, problem çox güman tuneldə və ya dev serverinizin əlçatanlığındadır. Publik URL‑i birbaşa brauzerdə açmağa cəhd edin: açılmırsa və ya Next.js səhvi ilə açılırsa, ilk növbədə onu düzəldin.
  2. Sonra ChatGPT işləyən vərəqdə brauzerin DevTools‑unu açın. Orada vidcetiniz üçün ayrıca iframe var və onun daxilində tanış Console vərəqi. openExternal düyməsini klikləyəndə heç nə baş vermirsə, “window.openai is undefined” və ya digər JS səhvlərinin olub‑olmadığına baxın. Belə səhv varsa — çox güman vidceti ChatGPT‑də yox (tunel URL‑i ilə birbaşa) yoxlayırsınız və ya 'use client'; direktivini unutmusunuz.
  3. Paralel olaraq npm run dev olan terminala baxın. Oraya build xətaları (TypeScript, ESLint, kompilyasiya) yağırsa, yaxşı halda ChatGPT köhnə kodu görəcək, pis halda ümumiyyətlə heç nə görməyəcək. Xəta yoxdursa, amma yenilənməni görmürsünüzsə, tunelin hələ aktiv olduğuna əmin olun: bir çox tunel servisi fəaliyyətsizlik taymautuna görə sessiyanı bağlayır.

Daha bir tipik hal: hər şey localhost‑da işləyir, amma tunel vasitəsilə müraciətdə 404 və ya qəribə bir səhifə alırsınız. O zaman baza yolu (/widget və ya /), basePath/assetPrefix sazlamalarını (əgər artıq toxunmusunuzsa) və Dev Mode‑da yazılmış ünvanı diqqətlə yoxlayın.

10. Bir az “təmizlik” haqqında: proseslərin dayandırılması

Xırda görünür, amma praktikada çox faydalıdır. Yeni başlayanlar tez‑tez unudurlar ki, həm dev server, həm də tunel — arxa planda işləməyə davam edən ayrı proseslərdir.

Əgər qəfil “3000 portu artıq məşğuldur” mesajını görsəniz, bəlkə hardasa terminalların dərinliyində köhnə npm run dev gizlənib. Windows‑da bu bəzən Task Manager ətrafında “ələşmələrə” çevrilir, macOS və Linux‑da isə prosesin işə salındığı terminalda Ctrl + C kömək edir.

Eyni şey tunelə də aiddir: ard‑arda bir neçə tunellə eksperimenti etmisinizsə və ya köhnəni bağlamağı unutmusunuzsa, App‑inizin Dev Mode‑da hansı URL‑ə bağlı olduğunu qarışdırmaq asandır. Vərdiş qazanın: sessiyanı bitirirsinizsə — tuneli söndürün, dev serveri dayandırın və növbəti işə salmada təmiz səhifədən başlayın.

11. İlk smoke testdə tipik səhvlər

Səhv №1: publik HTTPS URL əvəzinə localhost istifadə etmək.
Tez‑tez belə olur: Dev Mode‑da təsadüfən http://localhost:3000 göstərirsiniz və ya ümumiyyətlə tuneli unudursunuz. Maşınınızda hər şey işləyir, amma buludda yaşayan ChatGPT fiziki olaraq localhost‑a çata bilmir. Çarə sadədir: App sazlamalarında düzgün yol ilə məhz tunelin publik HTTPS ünvanının göstərildiyini yoxlayın (/mcp və ya kök — şablondan asılı olaraq).

Səhv №2: vidcet faylında 'use client'; direktivini unutmaq.
Gözəl React kodu yazırsınız, onClick əlavə edirsiniz, window.openai‑a müraciət edirsiniz, amma Next.js səssizcə səhifəni server komponenti edir. Yaxşı halda “window is not defined” xətası alacaqsınız, pis halda komponent ümumiyyətlə toplanmayacaq. Brauzer API‑lərinə çıxış üçün vidcet mütləq klient komponent olmalıdır, bunu isə ilk sətrdəki 'use client'; bildirir.

Səhv №3: openExternal əvəzinə birbaşa window.open() çağırmaq.
Bəzən window.open('https://example.com') etmək daha asan görünür. Adi brauzerdə bu hələ işləyə bilər, amma ChatGPT sandboxunda proqnozlaşdırılmayan davranış alacaqsınız: tam ignorlamadan tutmuş bloklanmaya qədər. ChatGPT Apps üçün düzgün yol — keçidin açılmasını hosta delegasiya edən və bütün təhlükəsizlik siyasətlərinə əməl edən window.openai.openExternal({ href }).

Səhv №4: TypeScript window.openai barədə irad tutur və tərtibatçı bunu tipləri söndürməklə “müalicə edir”.
Bəzən ümiddən kəsilərək faylın əvvəlində // @ts-nocheck yazırlar. Bu, kompilyasiya xətalarından qurtarır, amma eyni zamanda faylda bütün TypeScript‑i də söndürür. Xeyli təhlükəsiz çıxış — ya window ətrafında nöqtəvi as any istifadə etmək, ya da ayrı faylda window.openai üçün minimal interfeys təsvir etməkdir. Bu modulda biz openExternalSafe adlı kiçik helper seçdik və (window as any) tətbiq etdik, səliqəli tipizasiyanı isə sonra əlavə edəcəyik.

Səhv №5: nəticəyə yalnız localhost‑da baxmaq, ChatGPT daxilində yox.
Bəzən http://localhost:3000/widget açılırsa, bunu kifayət hesab etmək cazibədar görünür. Amma bu modulun məğzi məhz App‑i ChatGPT daxilində görməkdir. Adi brauzerdə hər şeyin yaxşı olması hələ ChatGPT‑nin iframe‑i düzgün yaradacağını, resursları tunel vasitəsilə götürəcəyini və CORS/CSP‑də ilişməyəcəyini təmin etmir. Tamhüquqlu smoke test həmişə App‑in real olaraq ChatGPT interfeysində işə salınması addımını ehtiva edir.

Səhv №6: unudulmuş və ya qopmuş tunel.
Kodu yeniləmisiniz, amma ChatGPT‑də köhnə vidcet versiyası asılıb qalır və ya ümumiyyətlə heç nə yüklənmir. Çox vaxt məlum olur ki, tunel taymauta görə bağlanıb, amma Developer Mode hələ də köhnə URL‑ə baxır. Tunel URL‑ini adi brauzerdə açanda səhv görürsünüzsə — əvvəlcə tuneli bərpa edin, sonra Apps SDK‑ya “günah” atın.

Səhv №7: iframe daxilində konsolu ignor etmək.
SPA təcrübəsi olan tərtibatçılar adətən tətbiqlərinin DevTools‑unda console.log‑a baxmağa öyrəşiblər, amma ChatGPT daxilində bu iframe‑dir və DevTools‑da düzgün frame seçmək lazımdır. Yalnız yuxarı səviyyəyə baxsanız, bəlkə də bir dənə belə səhv görməyəcəksiniz, halbuki vidcet daxilində hər şey çoxdan qırmızıdır. “Mütləq vidcet‑iframe üçün DevTools‑u açmaq” vərdişi əsəbləri çox qoruyur.

1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
İlk ChatGPT tətbiqi
İlk ChatGPT tətbiqi: şablon, Dev Mode, tunel
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION