where lang is the notebook's language", () => {
        expect( codeEl.className ).toBe(`lang-${notebookLang}`)
      })
      it("has attribute data-language with the notebook's language", () => {
        expect( codeEl.getAttribute('data-language') ).toBe(notebookLang)
      })
      it('has $source converted using codeHighlighter() as the innerHTML', () => {
        expect( codeHighlighter ).toBeCalledWith(join(cell.source), expect.anything())
        expect( codeEl.innerHTML ).toEqual(mockLastResult(codeHighlighter))
      })
    })
    describe('when the notebook does not have metadata.language_info.name', () => {
      const myNotebook: Notebook = { ...notebook, metadata: {} }
      const notebookLang = 'python'
      it('uses the default language: python', () => {
        const result = renderer.renderSource(cell, myNotebook)
        const codeEl = result.firstChild!.firstChild as HTMLElement
        expect( codeEl.getAttribute('data-language') ).toBe(notebookLang)
        expect( codeEl.classList ).toContain(`lang-${notebookLang}`)
        expect( codeHighlighter ).toBeCalledWith(expect.anything(), notebookLang)
      })
    })
  })
  describe('.renderOutput', () => {
    const cell = { ...fixtures.CodeCell, execution_count: null }
    describe.each([
      'renderDisplayData', 'renderExecuteResult', 'renderStream', 'renderError',
    ] as const)('with %s output', (funcName) => {
      const type = funcName.replace('render', '')
      const output = (fixtures as any)[type]
      let result: HTMLElement
      beforeEach(() => {
        renderer[funcName] = rendererMock(type)
        result = renderer.renderOutput(output, cell)
      })
      it('returns div.output', () => {
        expect( result ).toMatchElement(
          
        )
      })
      it(`returns element with the output rendered using .${funcName}() as the only child`, () => {
        expect( renderer[funcName] ).toBeCalledWith(output)
        expect( result.children ).toHtmlEqual([mockLastResult(renderer[funcName])])
      })
      describe('when the cell has non-null execution_count', () => {
        const cell = { ...fixtures.CodeCell, execution_count: 2 }
        it('returns element with attributes data-execution-count and data-prompt-number', () => {
          const result = renderer.renderOutput(output, cell)
          expect( result.attributes ).toMatchObject({
            'data-execution-count': String(cell.execution_count),
            'data-prompt-number': String(cell.execution_count),
          })
        })
      })
    })
    describe('with unsupported output type', () => {
      const output = {
        output_type: 'whatever',
      } as any
      const cell = {
        ...fixtures.CodeCell,
        execution_count: null,
        output: [output],
      }
      it('returns div with comment "Unsupported output type"', () => {
        expect( renderer.renderOutput(output, cell) ).toHtmlEqual(
          
        )
      })
    })
  })
  describe('.renderDisplayData', () => {
    function displayDataWith (data: MimeBundle): DisplayData {
      return { ...fixtures.DisplayData, data }
    }
    function withMimeData (
      mimeType: string,
      value: MultilineString,
      fn: (output: DisplayData, value: MultilineString) => void,
    ): void {
      describe(mimeType, () => {
        describe('as a string', () => {
          const data = join(value)
          fn(displayDataWith({ [mimeType]: data }), data)
        })
        describe('as an array', () => {
          const data = arrify(value)
          fn(displayDataWith({ [mimeType]: data }), data)
        })
      })
    }
    describe('with single data of unsupported MIME type', () => {
      const displayData = displayDataWith({ 'text/non-sense': 'whaat' })
      it('returns div.empty-output', () => {
        expect( renderer.renderDisplayData(displayData) ).toHtmlEqual(
          
        )
      })
    })
    describe('with single data of built-in MIME type', () => {
      ;['image/png', 'image/jpeg'].forEach(mimeType => {
        withMimeData(mimeType, ['aW1hZ2Ug\n', 'ZGF0YQ=='], (output) => {
          it('returns img.image-output with the data in the src attribute', () => {
            expect( renderer.renderDisplayData(output) ).toHtmlEqual(
               )
          })
        })
      })
      // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
      ;([
        /* mimeType     |  classes       */
        ['image/svg+xml', ['svg-output']  ],
        ['text/svg+xml' , ['svg-output']  ],
        ['text/html'    , ['html-output'] ],
        ['text/latex'   , ['latex-output']],
      ] as Array<[string, string[]]>).forEach(([mimeType, classes]) => {
        withMimeData(mimeType, 'data', (output, data) => {
          it(`returns div${classes.map(x => `.${x}`)} with the data as content`, () => {
            expect( renderer.renderDisplayData(output) ).toHtmlEqual(
            )
          })
        })
      })
      // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
      ;([
        /* mimeType     |  classes       */
        ['image/svg+xml', ['svg-output']  ],
        ['text/svg+xml' , ['svg-output']  ],
        ['text/html'    , ['html-output'] ],
        ['text/latex'   , ['latex-output']],
      ] as Array<[string, string[]]>).forEach(([mimeType, classes]) => {
        withMimeData(mimeType, 'data', (output, data) => {
          it(`returns div${classes.map(x => `.${x}`)} with the data as content`, () => {
            expect( renderer.renderDisplayData(output) ).toHtmlEqual(
              
                {{__html: join(data) }}
              
            )
          })
        })
      })
      withMimeData('text/markdown', ['Lorem\n', 'ipsum'], (output, data) => {
        it('returns div.html-output with the data converted using markdownRenderer() as content', () => {
          expect( renderer.renderDisplayData(output) ).toHtmlEqual(
            
              {{__html: mockLastResult(markdownRenderer) }}
            
          )
          expect( markdownRenderer ).toBeCalledWith(join(data))
        })
      })
      withMimeData('text/plain', '>_<', (output) => {
        it('returns pre.text-output with html-escaped data', () => {
          expect( renderer.renderDisplayData(output) ).toHtmlEqual(
            { '>_<' }
          )
        })
      })
      withMimeData('application/javascript', 'alert("Hello &!")', (output, data) => {
        it('returns script with the data', () => {
          expect( renderer.renderDisplayData(output) ).toHtmlEqual(
            
          )
        })
      })
    })
    describe('with single data of non-built-in MIME type', () => {
      withMimeData('text/custom', 'Lorem ipsum', (output, data) => {
        it('renders the data using the associated external renderer', () => {
          expect( renderer.renderDisplayData(output) ).toHtmlEqual(
            mockLastResult(dataRenderers['text/custom'])
          )
          expect( dataRenderers['text/custom'] ).toBeCalledWith(join(data))
        })
      })
    })
    describe('with multiple data', () => {
      const mimeBundle = {
        'text/plain': 'Lorem ipsum',
        'text/html': 'Lorem ipsum
',
        'text/unknown': '???',
      }
      const output = displayDataWith(mimeBundle)
      it('renders the data of the MIME type with a higher priority', () => {
        expect( renderer.renderDisplayData(output) ).toHtmlEqual(
          
            {{__html: mimeBundle['text/html'] }}
          
        )
      })
      test('the provided dataRenderers have higher priority than the built-ins', () => {
        const mimeBundle = {
          'text/custom': '>>Lorem ipsum<<',
          'text/html': 'Lorem ipsum
',
        }
        const output = displayDataWith(mimeBundle)
        expect( renderer.renderDisplayData(output) ).toHtmlEqual(
          mockLastResult(dataRenderers['text/custom'])
        )
      })
    })
    describe('when built with external renderer for the built-in type', () => {
      const dataRenderer = rendererMock('DisplayData')
      beforeEach(() => {
        renderer = new NbRenderer(elementCreator, {
          ...rendererOpts,
          dataRenderers: { 'text/plain': dataRenderer },
        })
      })
      it('renders the data using the external renderer instead of the built-in', () => {
        const data = 'allons-y!'
        const output = displayDataWith({ 'text/plain': [data] })
        expect( renderer.renderDisplayData(output) ).toBe(mockLastResult(dataRenderer))
        expect( dataRenderer ).toBeCalledWith(data)
      })
    })
  })
  describe('.renderError', () => {
    const error = fixtures.Error
    const traceback = error.traceback.join('\n')
    it('returns pre.error.pyerr with inner $traceback converted using ansiCodesRenderer', () => {
      expect( renderer.renderError(error) ).toHtmlEqual(
        
          {{__html: mockLastResult(ansiCodesRenderer) }}
        
      )
      expect( ansiCodesRenderer ).toBeCalledWith(traceback)
    })
  })
  describe('.renderStream', () => {
    eachMultilineVariant(fixtures.Stream, 'text', (stream) => {
      const text = join(stream.text)
      it('returns pre.$name with inner $text converted using ansiCodesRenderer', () => {
        expect( renderer.renderStream(stream) ).toHtmlEqual(
          
            {{__html: mockLastResult(ansiCodesRenderer) }}
          
        )
        expect( ansiCodesRenderer ).toBeCalledWith(text)
      })
    })
  })
})
function eachMultilineVariant  (
  obj: T,
  propName: K,
  fn: (obj: T) => void,
): void {
  const propValue = obj[propName]
  describe(`when ${propName} is an array`,
    () => fn({ ...obj, [propName]: arrify(propValue) }))
  describe(`when ${propName} is a string`,
    () => fn({ ...obj, [propName]: join(propValue) }))
}
const genStubElement = jest.fn((type: string) => {
  const id = genStubElement.mock.calls.filter(args => args[0] === type).length
  const el = document.createElement('stub')
  el.setAttribute('type', type)
  el.setAttribute('id', id.toString())
  return el
})
function stubElement (type: string): HTMLElement {
  return genStubElement(type)
}
function rendererMock (type: string) {
  return jest.fn(() => stubElement(type))
}
function join (input: MultilineString): string {
  return Array.isArray(input) ? input.join('') : input
}