text: import { Projects, ProjectEntry } from "./projects.js";
  test('ProjectEntry: Happy Path', () => {
    let json = {
      topicName : "ABCD",
      topicDescription: "EFGHI",
      displayName: "JKLMNO",
      displayDescription: "PQRSTU",
      displayImage: "VWXYZ",
      page: "12345"
    };
  
    let projectEntry = new ProjectEntry(json);
    expect(projectEntry.topicName).toBe('ABCD');
    expect(projectEntry.topicDescription).toBe('EFGHI');
    expect(projectEntry.name).toBe('JKLMNO');
    expect(projectEntry.description).toBe('PQRSTU');
    expect(projectEntry.image).toBe('VWXYZ');
    expect(projectEntry.page).toBe('12345');
  });
  
  test('ProjectEntry: Data Breaks', () => {
    let json = {
      topicName : "ABCD",
      topicDescription: "EFGHI",
      displayName: "JKLMNO",
      displayDescription: "PQRSTU",
      displayImage: "VWXYZ",
      page: "12345"
    };
  
    delete json.topicName;
    expect(new ProjectEntry(json).topicName).toBe(undefined);
    delete json.topicDescription;
    expect(new ProjectEntry().topicDescription).toBe(undefined);
    delete json.displayName;
    expect(new ProjectEntry().name).toBe(undefined);
    delete json.displayDescription;
    expect(new ProjectEntry().description).toBe(undefined);
    delete json.displayImage;
    expect(new ProjectEntry().image).toBe(undefined);
    delete json.page;
    expect(new ProjectEntry().page).toBe(undefined);
  });
  
  test('Projects: Iteration', () => {
    /* Generated by projects_genTest.js - Begin ***********************************************************************/
    const nEntriesExpected = 9;
    const json = {
      "topics": [
        {
          "displayName": "e'*9VxGV#y(UT-%Vem{9eyo`mbSO>]|a!Z^W2tt'>mdj4;CJT%1&%y4!St[f5NH_s>yh)%W[h2cJF9jpVC1+IcL@qQP0Os0.5sRMxo8[$}QOT{E",
          "displayDescription": "\\k~)'Zzzi_a{,}@^9u0m!BP2 s?K&?T]A9d)jRE",
          "projects": [
            {
              "displayName": "=^pdFW[&+H462eG|t&r6T,d&G)'n'v0i+<sn+2zsuqX.<Y1%5Hyf|sS71A&D.tgLH#jGW]GJkzg; q{H<0&WK.5^e&7NW{gT-U3;^{&>K$}BQ*wS g#lA^&=/4|u",
              "displayDescription": "8fe AHMu0@rsP,.Kl}L,q80+a\"1KBx;24zLeb~j%ay[vAhLf~^6nzHQ2?HwL9hbX?4}Ho%`MPKsj$^z",
              "displayImage": "tLm&R;yN'",
              "page": "D1m>HaTq2B'YlItK,3gR_LebS}votwxag1RYWMKM>_oK,DKKqp^I>:r7y]cpr:3 :*cyXh#_k<fh"
            },
            {
              "displayName": "cQFO\\9oM\"$*rw{WH\"5x^~HgPNMa\"xLN|p]}F_A{=+%c\\J~`jsB*i`B;t/{Gwfc3#lKsjScIOm6\\V59H",
              "displayDescription": "\"n82KYuuAd%Qs=i",
              "displayImage": "=R:UUA4aP'0&b$\\EAP|$Ob'}W}T]J^mj&pn}LpbH}](:a_Iw\\@#?S*5;4?x_JUsdA%o8SykECACpY-r8Mr",
              "page": "*r]//*S.h[-@Ypc\\pK1Xy"
            },
            {
              "displayName": ":\"5wn~]xye",
              "displayDescription": "!A#`!\\rANO,1uhb(Da%\\MCW*sL:G*s9N.D\\jkG?]&Ra>6e*9Up.=u?4WOD Z1a&DY;_q~v-N8+<vPgCM@^Q\\\\^SERi6C",
              "displayImage": "_]ja%TV);.;4Q>y#hf&=p7}$i5p:VEh1H2i7P;4\"v[f1uBxZ2<)6pPHOqAp",
              "page": "4Fj<8(q/ShO6}m]$R\\[u2V}qEI+WnC1P[v[Ny~ef4SS;=^y_ 7ss/fFr]_OWIY~;idI<LNHrw=g2"
            }
          ]
        },
        {
          "displayName": "n2'1p Z{!A;dB",
          "displayDescription": "*V^2@uo;#Ow293ic{_'S3QM0@@Ckth4gS46~dvlQ40V.ns2yB[b0503qPM\"h.Bv-*QQh@",
          "projects": [
            {
              "displayName": "D{Eiim9-*Y*!.mzGF{2w 5I0060,x_C.SI=c9s*1ZOH*rI&3OLq=v2e-^&,Q\"I oM=7,E>WAcfP&>\\8Od9#O7U5]jIQ'",
              "displayDescription": ")]W[[br",
              "displayImage": "w4H?p/(Tm2gc3adMfb~ [x)z;};a+s'3]J:aPO|=/i1$dp+4=%4s/\"bL4!3yhT-_$ZuK1=W@/b|#dfxx<af b]@ >sJs~cI3moQ1S",
              "page": "h-L?N]b3)#!E"
            },
            {
              "displayName": "\"x!D",
              "displayDescription": "!FD.CaUaua4P/U,))o?1,EK[KC\"CDjo\\fNxd@XTsziCZ^XiR$Wwq3rft5uRw6euo9X3y:\\:c|SR:jZS>wP}.[%\\=",
              "displayImage": "5&a?WcwFpQIh*zyR*Z![#&7g5D8``:%AFH#c.t^ 6k|.Y,Se\":cvdqi H_j=t-0\\qhT0\\t\\\\\"cJ28h/NaR-GO}UmFVMB|hfu",
              "page": "FN[kK3@Eysaz:8}xswT6*]vbO-}4UPuVi$8D_JBqoG{oVw#}^;DGyh\\Rj"
            },
            {
              "displayName": "8fveV:v#u)>`~}T:OQu/J3km#pE\"l)82SB05k8+YG,*<9;Mx9ScRt,OSIo.h6)$zpxS;B<F)(X2f=}e",
              "displayDescription": "q$ZYfj-gH2slWc/I[>~lf2mNJZ(f7QRV}\"Op`&mV#rw^horEEri@=92YX}Am>w{FUA1\"o\"-BCfL^%r;h/8:A5xZi9.!Wy'",
              "displayImage": "V&-I8)+Ma8C]j0~kw?B5J<;wu&uw=n2^T7MdJT7]D);_@5X9^RAt\\9`h!io]pFNltYf'#?gQ[Xw`ZPhyd`ap QX_Mfxr9iN,s5U^",
              "page": "'Uv2@lStGE]H:P0N.-oD0+W.o[YesGc_H"
            }
          ]
        },
        {
          "displayName": "H",
          "displayDescription": "Z%*lw+!#fL_Bjo,teeN0.'dHo7Cga7;Ix)a($h99Mt,b.\"j",
          "projects": [
            {
              "displayName": "XOM1qCDTE#R&~x-@^l+$+a,*c,iZZh\\Y2$\"n_$G5g\\0vwsbb/$WI|0{uockV!G{17p'e\\GGr*{",
              "displayDescription": "#~:~s&ygr&[qyak}~5<",
              "displayImage": "+F|FUZ\"dQX_}t(6CjrD#M!-Yts>A\\7EV>jEEkHaMmFlZcfIY4#?sngC%\\fh^X*}S#:e3EFS1g:2U)}ManWGa()[v,>:0bBMx[8N=K6~;Ih%I^2JB\\HK-*X}",
              "page": "GU}tM2*%F&KlS[_5DuD0f*g0H=16ol@[g?xu<\"r\\nm1Lg`F$/}7'\\i"
            },
            {
              "displayName": "#j]8OXzgc1A9C'&Ku {4:\"n3yZ,>L[n+w:7(Bh-ei)u",
              "displayDescription": "NTu@K7|UJo>A;m!VJ$#%1HZ>4!ggy!0GSo$XpJ/n\"GTnZhH6^VwB}_H@p_m?",
              "displayImage": "d(roP2b5PYm2@[^;*U1MS!M}+%r8C^K>/wZJ9`uYX}B~5mwpr[xE)2IC:|j!",
              "page": "gv&GZns2=@Rnos?7+G\"^>N}Ys1{Jwl/E3c<dO>42QZ}\"9wInNdFB3~O62m(%d"
            },
            {
              "displayName": "^&7cz*8dt1kb%t>]q/5 b~8}WP#cioYamLR{.@`XIkyy[l,Q~CL^~",
              "displayDescription": "'F`a$5Z(i{;h33&'~V\"ac<W9if:'8e8<`^>OfmWf",
              "displayImage": "_s.26o)Ao&0?kILP4#V{pgKDy@Kl0WxZ&6I]I#B&",
              "page": "L%:628ni9 B4;2mY_4V#t0Qi&!!`/\\EG@f@^"
            }
          ]
        }
      ]
    }
  /************************************************************************Generated by projects_genTest.js - End ***/
  
  
    let db = new Map();
    let tn = 0, pn = 0;
    for (let topic of json.topics) {
      for (let project of json.topics[tn].projects) {
        let lkup = topic.displayName + topic.displayDescription + project.displayName;
        db.set(lkup, [tn, pn]);
        pn++;
      }
      pn = 0; tn++;
    }
    const projects = new Projects(json);
    let nEntries = 0;
    for (let entry of projects) {
      nEntries++;
      let lkup = entry.topicName + entry.topicDescription + entry.name; 
      expect(db.has(lkup)).toBe(true);
      let [tn, pn] = db.get(lkup);
      expect(entry.description).toBe(json.topics[tn].projects[pn].displayDescription);
      expect(entry.image).toBe(json.topics[tn].projects[pn].displayImage);
      expect(entry.name).toBe(json.topics[tn].projects[pn].displayName);
      expect(entry.page).toBe(json.topics[tn].projects[pn].page);
      expect(entry.topicDescription).toBe(json.topics[tn].displayDescription);
      expect(entry.topicName).toBe(json.topics[tn].displayName);
    }
    expect(nEntries).toBe(nEntriesExpected);
  });
  
  test('Projects: projects.json', () => {
    const projects = new Projects();
    let nEntries = 0;
    for(let entry of projects)
    {
      nEntries++;
      expect(entry.description).toBeDefined();
      expect(entry.image).toBeDefined();
      expect(entry.name).toBeDefined();
      expect(entry.page).toBeDefined();
      expect(entry.topicDescription).toBeDefined();
      expect(entry.topicName).toBeDefined();
    }
    expect(nEntries).toBe(6);
  });
  