text: const docutils = require('../lib/index')
  
  const basicDoc = require('./documents/hello.xml')
  const longDoc = require('./documents/index.xml')
  const listAttrsDoc = require('./documents/listAttrs.xml')
  const spacesDoc = require('./documents/spaces.xml')
  
  describe('parser', () => {
    test('basic document', () => {
      const result = docutils.parse(basicDoc)
  
      expect(result).toEqual({
        tag: 'document',
        attributes: {
          source: '.../hello.rst'
        },
        children: [
          {
            tag: 'section',
            attributes: {
              ids: 'hello-world',
              names: 'hello, world!'
            },
            children: [
              {
                tag: 'title',
                attributes: {},
                children: ['Hello, world!']
              },
              {
                tag: 'paragraph',
                attributes: {},
                children: ['This file is empty.']
              }
            ]
          }
        ]
      })
    })
  
    test('document with spaces', () => {
      const result = docutils.parse(spacesDoc)
  
      expect(result).toEqual({
        tag: 'document',
        attributes: {
          source: '.../spaces.rst'
        },
        children: [
          {
            tag: 'section',
            attributes: {
              ids: 'spaces',
              names: 'spaces'
            },
            children: [
              {
                tag: 'title',
                attributes: {},
                children: ['spaces']
              },
              {
                tag: 'paragraph',
                attributes: {},
                children: [
                  'This is a sentence with ',
                  {
                    tag: 'strong',
                    attributes: {},
                    children: ['significant']
                  },
                  ' whitespace.'
                ]
              }
            ]
          }
        ]
      })
    })
  
    test('long document', () => {
      const result = docutils.parse(longDoc)
      expect(result).toMatchSnapshot()
    })
  
    test('invalid document', () => {
      expect(() => docutils.parse('invalid xml')).toThrow()
    })
  
    test('list attributes', () => {
      const result = docutils.parse(listAttrsDoc)
  
      expect(result.children[0].children[1].children[0]).toEqual({
        tag: 'index',
        attributes: {
          entries: [
            'single',
            'Python Enhancement Proposals; PEP 287',
            'index-0',
            '',
            null
          ]
        },
        children: []
      })
    })
  })
  
  describe('parser plugins', () => {
    test('execution order', () => {
      let count = 0
      const first = jest.fn(() => expect(count++).toEqual(0))
      const second = jest.fn(() => expect(count++).toEqual(1))
  
      docutils.parse(basicDoc, [first, second])
  
      expect(first).toBeCalled()
      expect(second).toBeCalled()
    })
  
    test('can use parser', () => {
      const plugin = jest.fn(parser => {
        expect(parser).toBeInstanceOf(docutils.DocumentParser)
      })
  
      docutils.parse(basicDoc, [plugin])
  
      expect(plugin).toBeCalled()
    })
  })
  
  describe('parser events', () => {
    let parser
  
    beforeEach(() => {
      parser = new docutils.DocumentParser()
    })
  
    test('document:start', () => {
      const callback = jest.fn(() => {
        expect(parser.stack[0].children.length).toEqual(0)
      })
  
      parser.on('document:start', callback).parse(basicDoc)
  
      expect(callback).toBeCalled()
    })
  
    test('document:end', () => {
      const callback = jest.fn(document => {
        expect(parser.stack).toEqual([])
        expect(document).toBe(parser.document)
      })
  
      parser.on('document:end', callback).parse(basicDoc)
  
      expect(callback).toBeCalled()
    })
  
    test('element', () => {
      const visits = ['document', 'section', 'paragraph', 'title']
  
      const callback = jest.fn(element => {
        expect(element.tag).toEqual(visits.pop())
      })
  
      parser.on('element', callback).parse(basicDoc)
  
      expect(callback).toBeCalled()
      expect(visits).toEqual([])
    })
  
    test('element:not_present_in_document', () => {
      const callback = jest.fn()
  
      parser.on('element:not_present_in_document', callback).parse(basicDoc)
  
      expect(callback).not.toBeCalled()
    })
  
    test('element:title', () => {
      const callback = jest.fn(element => {
        expect(element).toBe(parser.stack[0].children[0].children[0].children[0])
      })
  
      parser.on('element:title', callback).parse(basicDoc)
  
      expect(callback).toBeCalled()
    })
  })
  