class TestIXBRLViewer(unittest.TestCase):
    def setUp(self):
        self.cash_concept = Mock(qname=Mock(localName='Cash',
                                            prefix='us-gaap',
                                            namespaceURI='http://viewer.com'))

        to_concept = Mock(qname=Mock(localName='to_concept',
                                     prefix='us-gaap',
                                     namespaceURI='http://viewer.com'))
        from_concept = Mock(qname=Mock(localName='from_concept',
                                       prefix='us-gaap',
                                       namespaceURI='http://viewer.com'))

        dimension_concept = Mock(qname=Mock(localName='dimension',
                                            prefix='us-gaap',
                                            namespaceURI='http://viewer.com'))

        member_concept = Mock(qname=Mock(localName='member',
                                         prefix='us-gaap',
                                         namespaceURI='http://viewer.com'))

        rel = Mock(fromModelObject=from_concept,
                   toModelObject=to_concept,
                   weight=1)

        dimension = Mock(dimensionQname=dimension_concept.qname,
                         memberQname=member_concept.qname,
                         dimension=dimension_concept,
                         member=member_concept)

        def isoformat_effect():
            return '01-01-19T00:00:00'

        context_1 = Mock(entityIdentifier=('scheme', 'ident'),
                         qnameDims={'d': dimension},
                         isInstantPeriod=False,
                         isStartEndPeriod=True,
                         startDatetime=Mock(isoformat=isoformat_effect),
                         endDatetime=Mock(isoformat=isoformat_effect))

        context_2 = Mock(entityIdentifier=('scheme', 'ident'),
                         qnameDims={},
                         isInstantPeriod=None,
                         isStartEndPeriod=None)

        fact_1 = Mock(id='fact_id',
                      qname=self.cash_concept.qname,
                      value=100,
                      isNumeric=False,
                      context=context_1,
                      concept=self.cash_concept,
                      format='format')

        fact_2 = Mock(id='fact_id',
                      qname=self.cash_concept.qname,
                      concept=self.cash_concept,
                      context=context_2,
                      isNumeric=True,
                      unit=None,
                      value=None,
                      decimals=None,
                      precision=None,
                      format=None)

        def fromModelObjects_effect(concept):
            return []

        def relationshipSet_effect(self, *args):
            return Mock(fromModelObject=fromModelObjects_effect,
                        modelRelationships=[rel])

        def info_effect(info, msg):
            # This is a no op for logging
            pass

        baseSets = defaultdict(list)
        baseSets[('http://www.xbrl.org/2003/arcrole/parent-child', 'ELR',
                  'linkqname', 'arcqname')] = []

        root = lxml.etree.Element('root')
        lxml.etree.SubElement(root, '{http://www.w3.org/1999/xhtml}body')

        self.modelDocument = Mock(xmlDocument=lxml.etree.ElementTree(root))

        self.modelXbrl_1 = Mock(relationshipSet=relationshipSet_effect,
                                baseSets=baseSets,
                                facts=[fact_1],
                                info=info_effect,
                                modelDocument=self.modelDocument)
        self.modelXbrl_2 = Mock(relationshipSet=relationshipSet_effect,
                                baseSets=baseSets,
                                facts=[fact_2],
                                info=info_effect,
                                modelDocument=self.modelDocument)

        self.cash_concept.modelXbrl = self.modelXbrl_1
        to_concept.modelXbrl = self.modelXbrl_1
        from_concept.modelXbrl = self.modelXbrl_1
        dimension_concept.modelXbrl = self.modelXbrl_1
        member_concept.modelXbrl = self.modelXbrl_1
        self.builder_1 = IXBRLViewerBuilder(self.modelXbrl_1)
        self.builder_2 = IXBRLViewerBuilder(self.modelXbrl_2)

    @patch('arelle.XbrlConst.conceptLabel',
           'http://www.xbrl.org/2003/arcrole/concept-label')
    @patch('arelle.XbrlConst.conceptReference',
           'http://www.xbrl.org/2003/arcrole/concept-reference')
    def test_addConcept_simple_case(self):
        self.builder_1.addConcept(self.cash_concept)
        self.assertTrue(
            self.builder_1.taxonomyData.get('concepts').get('us-gaap:Cash'))

    @patch('arelle.XbrlConst.parentChild',
           'http://www.xbrl.org/2003/arcrole/parent-child')
    @patch('arelle.XbrlConst.summationItem',
           'http://www.xbrl.org/2003/arcrole/summation-item')
    def test_getRelationships_simple_case(self):
        modelXbrl = Mock(baseSets=defaultdict(list))
        builder = IXBRLViewerBuilder(modelXbrl)
        result = builder.getRelationnShips()
        self.assertDictEqual(result, {})

    @patch('arelle.XbrlConst.parentChild',
           'http://www.xbrl.org/2003/arcrole/parent-child')
    @patch('arelle.XbrlConst.summationItem',
           'http://www.xbrl.org/2003/arcrole/summation-item')
    def test_getRelationships_returns_a_rel(self):
        result = self.builder_1.getRelationnShips()
        self.assertTrue(
            result.get('ns0').get('ELR').get('us-gaap:from_concept'))

    @patch('arelle.XbrlConst.conceptLabel',
           'http://www.xbrl.org/2003/arcrole/concept-label')
    @patch('arelle.XbrlConst.conceptReference',
           'http://www.xbrl.org/2003/arcrole/concept-reference')
    @patch('arelle.XbrlConst.parentChild',
           'http://www.xbrl.org/2003/arcrole/parent-child')
    @patch('arelle.XbrlConst.summationItem',
           'http://www.xbrl.org/2003/arcrole/summation-item')
    @patch('arelle.XbrlConst.standardLabel',
           'http://www.xbrl.org/2003/role/label')
    @patch('arelle.XbrlConst.documentationLabel',
           'http://www.xbrl.org/2003/role/documentation')
    def test_createViewer(self):
        js_uri = 'ixbrlviewer.js'
        result = self.builder_1.createViewer(js_uri)
        body = result.getroot()[0]
        self.assertEqual(body[0].text, 'BEGIN IXBRL VIEWER EXTENSIONS')
        self.assertEqual(body[1].attrib.get('src'), js_uri)
        self.assertEqual(body[2].attrib.get('id'), 'taxonomy-data')
        self.assertEqual(body[2].attrib.get('type'), 'application/json')
        self.assertEqual(body[3].text, 'END IXBRL VIEWER EXTENSIONS')

    @patch('arelle.XbrlConst.conceptLabel',
           'http://www.xbrl.org/2003/arcrole/concept-label')
    @patch('arelle.XbrlConst.conceptReference',
           'http://www.xbrl.org/2003/arcrole/concept-reference')
    @patch('arelle.XbrlConst.parentChild',
           'http://www.xbrl.org/2003/arcrole/parent-child')
    @patch('arelle.XbrlConst.summationItem',
           'http://www.xbrl.org/2003/arcrole/summation-item')
    @patch('arelle.XbrlConst.standardLabel',
           'http://www.xbrl.org/2003/role/label')
    @patch('arelle.XbrlConst.documentationLabel',
           'http://www.xbrl.org/2003/role/documentation')
    def test_createViewer_bad_path(self):
        js_uri = 'ixbrlviewer.js'
        result = self.builder_2.createViewer(js_uri)
        body = result.getroot()[0]
        self.assertEqual(body[0].text, 'BEGIN IXBRL VIEWER EXTENSIONS')
        self.assertEqual(body[1].attrib.get('src'), js_uri)
        self.assertEqual(body[2].attrib.get('id'), 'taxonomy-data')
        self.assertEqual(body[2].attrib.get('type'), 'application/json')
        self.assertEqual(body[3].text, 'END IXBRL VIEWER EXTENSIONS')
 def test_getRelationships_simple_case(self):
     modelXbrl = Mock(baseSets=defaultdict(list))
     builder = IXBRLViewerBuilder(modelXbrl)
     result = builder.getRelationnShips()
     self.assertDictEqual(result, {})