<commit_before>import { Record, List } from 'immutable';

import React from 'react';
import { connect } from 'react-redux';

import page from 'page';

import StackChart from '../../../../shared/js/components/StackChart';
import {makeAmountString} from '../../../../shared/js/components/MoneyAmount';
import PageTitle from '../../../../shared/js/components/gironde.fr/PageTitle';
import SecundaryTitle from '../../../../shared/js/components/gironde.fr/SecundaryTitle';
import PrimaryCallToAction from '../../../../shared/js/components/gironde.fr/PrimaryCallToAction';
import Markdown from '../../../../shared/js/components/Markdown';
import {m52ToAggregated, hierarchicalAggregated} from '../../../../shared/js/finance/memoized';
import {flattenTree} from '../../../../shared/js/finance/visitHierarchical';
import {EXPENDITURES} from '../../../../shared/js/finance/constants';

import {urls, INSERTION_PICTO, ENFANCE_PICTO, HANDICAPES_PICTO, PERSONNES_AGEES_PICTO} from '../../constants/resources';

import FocusDetail from '../FocusDetail';
import FocusDonut from '../FocusDonut';

import colorClassById from '../../colorClassById';

/*

interface FocusSolidarityProps{
    currentYear,
    solidarityByYear: Map<year, YearSolidarityRecord>
}

*/

export function FocusSol({
    currentYear, currentYearSolidarity, solidarityByYear, screenWidth, urls
}) {

    const years = solidarityByYear.keySeq().toJS();

    // TODO current number (May 29th is 0.51 which is different than what was hardcoded (0.52))
    const solidarityProportion = currentYearSolidarity &&currentYearSolidarity.solidarityExpenditures/currentYearSolidarity.totalExpenditures;

    return React.createElement('article', {className: 'focus'},
        React.createElement('section', {},
            React.createElement(PageTitle, {text: 'Solidarités'}),
            React.createElement(Markdown, {},
                `Chaque jour, sur l’ensemble du territoire girondin, le Département poursuit le même objectif: réduire les inégalités géographiques et sociales auprès de toutes les populations. Le Département est un acteur incontournable de la lutte contre l’exclusion et la précarité. Il mène des actions sociales innovantes pour accompagner les personnes fragilisées. Les Girondins peuvent ainsi bénéficier d’allocations, prestations sociales et solidarité dans leur parcours de vie au quotidien.`
            )
        ),
        React.createElement('section', {className: 'top-infos'},
            React.createElement(FocusDonut, {
                proportion: solidarityProportion,
                outerRadius: screenWidth < 400 ? (screenWidth/2 - 20) : 188,
                innerText: [
                    `de dépenses Solidarités`,
                    `dans le total des dépenses`
                ]
            }),
            React.createElement('div', {},
                React.createElement(Markdown, {},
                    `**Avec 120 000 prestations allouées et ${currentYearSolidarity && (currentYearSolidarity.solidarityExpenditures/1000000).toFixed(0)} millions d'euros mobilisés en ${currentYear}, les dépenses de Solidarités pour soutenir les personnes fragilisées évoluent de +3,8% par rapport à 2016.**`),
                React.createElement(PrimaryCallToAction, {href: '#!/finance-details/DF-2', text: `en savoir plus`})
            ),
            React.createElement('div', {className: 'people-fraction'},
                React.createElement('div', {},
                    React.createElement('div', {}, 'Près de'),
                    React.createElement('div', {className: 'number'}, '1/10'),
                    React.createElement('div', {}, `personne accompagnée par le département`)
                )
            )
        ),
        React.createElement('section', {},
            React.createElement(SecundaryTitle, {text: `Les dépenses "Solidarités" augmentent pour tous les publics`}),
            React.createElement(StackChart, {
                WIDTH: screenWidth >= 800 + 80 ?
                    800 :
                    (screenWidth - 85 >= 600 ? screenWidth - 85 : (
                        screenWidth <= 600 ? screenWidth - 10 : 600
                    )),
                portrait: screenWidth <= 600,
                xs: years,
                ysByX: solidarityByYear.map(yearSolidarity => (new List([
                    yearSolidarity['DF-2-1'],
                    yearSolidarity['DF-2-2'],
                    yearSolidarity['DF-2-3'],
                    yearSolidarity['DF-2-4'],
                    yearSolidarity['DF-2-5']
                ]))),
                legendItems: [
                    {
                        id: 'DF-2-1',
                        colorClassName: colorClassById.get('DF-2-1'),
                        text: "Personnes en insertion",
                        url: `#!/finance-details/DF-2-1`
                    },
                    {
                        id: 'DF-2-2',
                        colorClassName: colorClassById.get('DF-2-2'),
                        text: "Personnes en situation de handicap",
                        url: `#!/finance-details/DF-2-2`
                    },
                    {
                        id: 'DF-2-3',
                        colorClassName: colorClassById.get('DF-2-3'),
                        text: "Personnes âgées",
                        url: `#!/finance-details/DF-2-3`
                    },
                    {
                        id: 'DF-2-4',
                        colorClassName: colorClassById.get('DF-2-4'),
                        text: "Enfance",
                        url: `#!/finance-details/DF-2-4`
                    },
                    {
                        id: 'DF-2-5',
                        colorClassName: colorClassById.get('DF-2-5'),
                        text: "Autres",
                        url: `#!/finance-details/DF-2-5`
                    }
                ],
                yValueDisplay: makeAmountString,
                onBrickClicked: (year, id) => { page(`#!/finance-details/${id}`); }
            })
        ),
        React.createElement('section', {},
            React.createElement(SecundaryTitle, {text: `Les actions et les aides varient en fonction des publics`}),
            React.createElement(Markdown, {}, `On distingue quatre catégories de public pouvant être aidé:

            - les personnes en insertion ou en situation de précarité,
            - les personnes en situation de handicap
            - les personnes âgées
            - les enfants

            Le Département définit sa propre politique et les actions qu’il met en œuvre pour chacun de ces publics : hébergements, prestations, subventions, allocations.`),
            React.createElement(FocusDetail, {
                className: 'insertion',
                title: 'Personnes en insertion',
                illustrationUrl: urls[INSERTION_PICTO],
                // (May 29th) different than what was hardcoded ("244 Millions €")
                amount: currentYearSolidarity ? currentYearSolidarity.get('DF-2-1') : undefined,
                proportion: currentYearSolidarity ? currentYearSolidarity.get('DF-2-1')/currentYearSolidarity.solidarityExpenditures : 1,
                text: `Le Revenu de Solidarité Active (RSA) représente près de 94% des aides financières versées aux personnes en insertion. Si vos ressources financières sont faibles ou inexistantes, vous pouvez demander le RSA. Plus d’infos sur: https://www.gironde.fr/insertion-rsa/vous-etes-un-particulier.`,
                highlights: [
                    {
                        strong: "+29%",
                        span: "de dépenses depuis 2013"
                    },
                    {
                        strong: "238,5 M€",
                        span: "dédiés au RSA en 2017"
                    },
                    {
                        strong: "+4.15%",
                        span: "d'allocations RSA par rapport à 2016"
                    }
                ],
                moreUrl: '#!/finance-details/DF-2-1'
            }),
            React.createElement(FocusDetail, {
                className: 'handicap',
                title: 'Personnes en situation de handicap',
                illustrationUrl: urls[HANDICAPES_PICTO],
                // (May 29th) different than what was hardcoded ("218 Millions €",)
                amount: currentYearSolidarity ? currentYearSolidarity.get('DF-2-2') : undefined,
                proportion: currentYearSolidarity ? currentYearSolidarity.get('DF-2-2')/currentYearSolidarity.solidarityExpenditures : 1,
                text: `Les aides du Département versées aux personnes en situation de handicap concernent en 2017:
- la Prestation de Compensation du Handicap (PCH) versée à 8520 personnes en 2017
- la prestation d’hébergement  qui a financé 2728 places d'hébergement en 2017 (2 763 en 2016)
- l’Allocation Compensation pour Tierce Personne (ACTP) a financé l'emploi d'aides à domicile pour 1125 personnes en 2017

L’objectif de ces aides est de soutenir la vie à domicile, faciliter l’accessibilité au logement, à l’emploi, à la scolarisation et à la vie sociale.`,
                highlights: [
                    {
                        strong: "78,9 M €",
                        span: "pour compenser la perte d'autonomie"
                    },
                    {
                        strong: "126,4 M€",
                        span: "pour des places d’hébergement"
                    },
                    {
                        strong: "8.12 M€",
                        span: "pour l'emploi de 757 aides à domicile"
                    }
                ],
                moreUrl: '#!/finance-details/DF-2-2'
            }),
            React.createElement(FocusDetail, {
                className: 'elderly',
                title: 'Personnes âgées',
                illustrationUrl: urls[PERSONNES_AGEES_PICTO],
                amount: currentYearSolidarity ? currentYearSolidarity.get('DF-2-3') : undefined,
                proportion: currentYearSolidarity ? currentYearSolidarity.get('DF-2-3')/currentYearSolidarity.solidarityExpenditures : 1,
                text: `L’Allocation Personnalisée d’Autonomie (APA) est la principale aide financière destinée à favoriser l’autonomie des personnes âgées.  Elle est versée directement à la personne ou à l’établissement en charge de cette personne, selon des critères d’attribution précis. https://www.gironde.fr/handicap-grand-age/aides-et-prestations-apa-pch-et-cmi L’application de la loi d’adaptation de la société au vieillissement (ASV) a entraîné une revalorisation de l’APA.`,
                highlights: [
                    {
                        strong: "143.6 M€",
                        span: "versés en 2017 pour l’APA"
                    },
                    {
                        strong: "+ 1.4%",
                        span: "en 2017"
                    },
                    {
                        strong: "34 446",
                        span: "bénéficiaires en 2017"
                    }
                ],
                moreUrl: '#!/finance-details/DF-2-3'
            }),
            React.createElement(FocusDetail, {
                className: 'childhood',
                title: 'Enfance',
                illustrationUrl: urls[ENFANCE_PICTO],
                // (May 29th) different than what was hardcoded ("168 Millions €")
                amount: currentYearSolidarity ? currentYearSolidarity.get('DF-2-4') : undefined,
                proportion: currentYearSolidarity ? currentYearSolidarity.get('DF-2-4')/currentYearSolidarity.solidarityExpenditures : 1,
                text: `Le Département veille à protéger les enfants et les jeunes majeurs quand leur sécurité, leur santé et leur éducation sont menacées. Ce sont les professionnels de l’Aide sociale à l’enfance (ASE) qui assurent un suivi au plus près des familles. Si le danger rend impossible le maintien dans sa famille, l’enfant est pris en charge et est confié à des professionnels (familles d’accueil, maison d’enfants à caractère social, centre départemental de l’enfance et de la famille, foyer de l’enfance).
https://www.gironde.fr/enfance-et-famille/protection-de-lenfance.`,
                highlights: [
                    {
                        strong: "177 M€",
                        span: "pour les Maisons d’Enfants à Caractère Sociale"
                    },
                    {
                        strong: "4269",
                        span: "enfants accueillis en établissement et familles d’accueil en 2017"
                    },
                    {
                        strong: "796",
                        span: " assistants familiaux pour l'accueil familial"
                    }
                ],
                moreUrl: '#!/finance-details/DF-2-4'
            })
        )
    );

}

const YearSolidarityRecord = Record({
    totalExpenditures: 0,
    solidarityExpenditures: 0,
    'DF-1-1': 0,
    'DF-1-2': 0,
    'DF-1-3': 0,
    'DF-1-4': 0,
    'DF-1-other': 0,
    'DF-2-1': 0,
    'DF-2-2': 0,
    'DF-2-3': 0,
    'DF-2-4': 0,
    'DF-2-5': 0
})

export default connect(
    state => {
        const { docBudgByYear, corrections, currentYear, screenWidth } = state;

        const solidarityByYear = docBudgByYear.map( ((instruction) => {
            const agg = m52ToAggregated(instruction, corrections);

            const hierAgg = hierarchicalAggregated(agg);

            const hierAggByPrestationList = flattenTree(hierAgg);

            const expenditures = hierAggByPrestationList.find(e => e.id === EXPENDITURES).total;
            let solidarityExpenditures = hierAggByPrestationList.find(e => e.id === 'DF-1').total;
            const ysrData = {};
            ['DF-1-1', 'DF-1-2', 'DF-1-3', 'DF-1-4', 'DF-2-1', 'DF-2-2', 'DF-2-3', 'DF-2-4', 'DF-2-5'].forEach(id => {
                ysrData[id] = hierAggByPrestationList.find(e => e.id === id).total;
            });

            let df1other = solidarityExpenditures - (ysrData['DF-1-1'] + ysrData['DF-1-2'] + ysrData['DF-1-3'] + ysrData['DF-1-4']);

            return new YearSolidarityRecord(Object.assign(
                {
                    totalExpenditures: expenditures,
                    solidarityExpenditures,
                    'DF-1-other': df1other
                },
                ysrData
            ))
        }))

        return {
            currentYear,
            currentYearSolidarity: solidarityByYear.get(currentYear),
            solidarityByYear,
            screenWidth,
            urls
        };
    },
    () => ({})
)(FocusSol);
<commit_msg>dernière correction<commit_after>import { Record, List } from 'immutable';

import React from 'react';
import { connect } from 'react-redux';

import page from 'page';

import StackChart from '../../../../shared/js/components/StackChart';
import {makeAmountString} from '../../../../shared/js/components/MoneyAmount';
import PageTitle from '../../../../shared/js/components/gironde.fr/PageTitle';
import SecundaryTitle from '../../../../shared/js/components/gironde.fr/SecundaryTitle';
import PrimaryCallToAction from '../../../../shared/js/components/gironde.fr/PrimaryCallToAction';
import Markdown from '../../../../shared/js/components/Markdown';
import {m52ToAggregated, hierarchicalAggregated} from '../../../../shared/js/finance/memoized';
import {flattenTree} from '../../../../shared/js/finance/visitHierarchical';
import {EXPENDITURES} from '../../../../shared/js/finance/constants';

import {urls, INSERTION_PICTO, ENFANCE_PICTO, HANDICAPES_PICTO, PERSONNES_AGEES_PICTO} from '../../constants/resources';

import FocusDetail from '../FocusDetail';
import FocusDonut from '../FocusDonut';

import colorClassById from '../../colorClassById';

/*

interface FocusSolidarityProps{
    currentYear,
    solidarityByYear: Map<year, YearSolidarityRecord>
}

*/

export function FocusSol({
    currentYear, currentYearSolidarity, solidarityByYear, screenWidth, urls
}) {

    const years = solidarityByYear.keySeq().toJS();

    // TODO current number (May 29th is 0.51 which is different than what was hardcoded (0.52))
    const solidarityProportion = currentYearSolidarity &&currentYearSolidarity.solidarityExpenditures/currentYearSolidarity.totalExpenditures;

    return React.createElement('article', {className: 'focus'},
        React.createElement('section', {},
            React.createElement(PageTitle, {text: 'Solidarités'}),
            React.createElement(Markdown, {},
                `Chaque jour, sur l’ensemble du territoire girondin, le Département poursuit le même objectif: réduire les inégalités géographiques et sociales auprès de toutes les populations. Le Département est un acteur incontournable de la lutte contre l’exclusion et la précarité. Il mène des actions sociales innovantes pour accompagner les personnes fragilisées. Les Girondins peuvent ainsi bénéficier d’allocations, prestations sociales et solidarité dans leur parcours de vie au quotidien.`
            )
        ),
        React.createElement('section', {className: 'top-infos'},
            React.createElement(FocusDonut, {
                proportion: solidarityProportion,
                outerRadius: screenWidth < 400 ? (screenWidth/2 - 20) : 188,
                innerText: [
                    `de dépenses Solidarités`,
                    `dans le total des dépenses`
                ]
            }),
            React.createElement('div', {},
                React.createElement(Markdown, {},
                    `**Avec 120 000 prestations allouées et ${currentYearSolidarity && (currentYearSolidarity.solidarityExpenditures/1000000).toFixed(0)} millions d'euros mobilisés en ${currentYear}, les dépenses de Solidarités pour soutenir les personnes fragilisées évoluent de +3,8% par rapport à 2016.**`),
                React.createElement(PrimaryCallToAction, {href: '#!/finance-details/DF-2', text: `en savoir plus`})
            ),
            React.createElement('div', {className: 'people-fraction'},
                React.createElement('div', {},
                    React.createElement('div', {}, 'Près de'),
                    React.createElement('div', {className: 'number'}, '1/10'),
                    React.createElement('div', {}, `personne accompagnée par le département`)
                )
            )
        ),
        React.createElement('section', {},
            React.createElement(SecundaryTitle, {text: `Les dépenses "Solidarités" augmentent pour tous les publics`}),
            React.createElement(StackChart, {
                WIDTH: screenWidth >= 800 + 80 ?
                    800 :
                    (screenWidth - 85 >= 600 ? screenWidth - 85 : (
                        screenWidth <= 600 ? screenWidth - 10 : 600
                    )),
                portrait: screenWidth <= 600,
                xs: years,
                ysByX: solidarityByYear.map(yearSolidarity => (new List([
                    yearSolidarity['DF-2-1'],
                    yearSolidarity['DF-2-2'],
                    yearSolidarity['DF-2-3'],
                    yearSolidarity['DF-2-4'],
                    yearSolidarity['DF-2-5']
                ]))),
                legendItems: [
                    {
                        id: 'DF-2-1',
                        colorClassName: colorClassById.get('DF-2-1'),
                        text: "Personnes en insertion",
                        url: `#!/finance-details/DF-2-1`
                    },
                    {
                        id: 'DF-2-2',
                        colorClassName: colorClassById.get('DF-2-2'),
                        text: "Personnes en situation de handicap",
                        url: `#!/finance-details/DF-2-2`
                    },
                    {
                        id: 'DF-2-3',
                        colorClassName: colorClassById.get('DF-2-3'),
                        text: "Personnes âgées",
                        url: `#!/finance-details/DF-2-3`
                    },
                    {
                        id: 'DF-2-4',
                        colorClassName: colorClassById.get('DF-2-4'),
                        text: "Enfance",
                        url: `#!/finance-details/DF-2-4`
                    },
                    {
                        id: 'DF-2-5',
                        colorClassName: colorClassById.get('DF-2-5'),
                        text: "Autres",
                        url: `#!/finance-details/DF-2-5`
                    }
                ],
                yValueDisplay: makeAmountString,
                onBrickClicked: (year, id) => { page(`#!/finance-details/${id}`); }
            })
        ),
        React.createElement('section', {},
            React.createElement(SecundaryTitle, {text: `Les actions et les aides varient en fonction des publics`}),
            React.createElement(Markdown, {}, `On distingue quatre catégories de public pouvant être aidé:

            - les personnes en insertion ou en situation de précarité,
            - les personnes en situation de handicap
            - les personnes âgées
            - les enfants

            Le Département définit sa propre politique et les actions qu’il met en œuvre pour chacun de ces publics : hébergements, prestations, subventions, allocations.`),
            React.createElement(FocusDetail, {
                className: 'insertion',
                title: 'Personnes en insertion',
                illustrationUrl: urls[INSERTION_PICTO],
                // (May 29th) different than what was hardcoded ("244 Millions €")
                amount: currentYearSolidarity ? currentYearSolidarity.get('DF-2-1') : undefined,
                proportion: currentYearSolidarity ? currentYearSolidarity.get('DF-2-1')/currentYearSolidarity.solidarityExpenditures : 1,
                text: `Le Revenu de Solidarité Active (RSA) représente près de 94% des aides financières versées aux personnes en insertion. Si vos ressources financières sont faibles ou inexistantes, vous pouvez demander le RSA. Plus d’infos sur: https://www.gironde.fr/insertion-rsa/vous-etes-un-particulier.`,
                highlights: [
                    {
                        strong: "+29%",
                        span: "de dépenses depuis 2013"
                    },
                    {
                        strong: "238,5 M€",
                        span: "dédiés au RSA en 2017"
                    },
                    {
                        strong: "+4.15%",
                        span: "d'allocations RSA par rapport à 2016"
                    }
                ],
                moreUrl: '#!/finance-details/DF-2-1'
            }),
            React.createElement(FocusDetail, {
                className: 'handicap',
                title: 'Personnes en situation de handicap',
                illustrationUrl: urls[HANDICAPES_PICTO],
                // (May 29th) different than what was hardcoded ("218 Millions €",)
                amount: currentYearSolidarity ? currentYearSolidarity.get('DF-2-2') : undefined,
                proportion: currentYearSolidarity ? currentYearSolidarity.get('DF-2-2')/currentYearSolidarity.solidarityExpenditures : 1,
                text: `Les aides du Département versées aux personnes en situation de handicap concernent en 2017:
- la Prestation de Compensation du Handicap (PCH) versée à 8520 personnes en 2017
- la prestation d’hébergement  qui a financé 2728 places d'hébergement en 2017
- l’Allocation Compensation pour Tierce Personne (ACTP) a financé l'emploi d'aides à domicile pour 1125 personnes en 2017

L’objectif de ces aides est de soutenir la vie à domicile, faciliter l’accessibilité au logement, à l’emploi, à la scolarisation et à la vie sociale.`,
                highlights: [
                    {
                        strong: "78,9 M €",
                        span: "pour compenser la perte d'autonomie"
                    },
                    {
                        strong: "126,4 M€",
                        span: "pour des places d’hébergement"
                    },
                    {
                        strong: "8.12 M€",
                        span: "pour l'emploi de 757 aides à domicile"
                    }
                ],
                moreUrl: '#!/finance-details/DF-2-2'
            }),
            React.createElement(FocusDetail, {
                className: 'elderly',
                title: 'Personnes âgées',
                illustrationUrl: urls[PERSONNES_AGEES_PICTO],
                amount: currentYearSolidarity ? currentYearSolidarity.get('DF-2-3') : undefined,
                proportion: currentYearSolidarity ? currentYearSolidarity.get('DF-2-3')/currentYearSolidarity.solidarityExpenditures : 1,
                text: `L’Allocation Personnalisée d’Autonomie (APA) est la principale aide financière destinée à favoriser l’autonomie des personnes âgées.  Elle est versée directement à la personne ou à l’établissement en charge de cette personne, selon des critères d’attribution précis. https://www.gironde.fr/handicap-grand-age/aides-et-prestations-apa-pch-et-cmi L’application de la loi d’adaptation de la société au vieillissement (ASV) a entraîné une revalorisation de l’APA.`,
                highlights: [
                    {
                        strong: "143.6 M€",
                        span: "versés en 2017 pour l’APA"
                    },
                    {
                        strong: "+ 1.4%",
                        span: "en 2017"
                    },
                    {
                        strong: "34 446",
                        span: "bénéficiaires en 2017"
                    }
                ],
                moreUrl: '#!/finance-details/DF-2-3'
            }),
            React.createElement(FocusDetail, {
                className: 'childhood',
                title: 'Enfance',
                illustrationUrl: urls[ENFANCE_PICTO],
                // (May 29th) different than what was hardcoded ("168 Millions €")
                amount: currentYearSolidarity ? currentYearSolidarity.get('DF-2-4') : undefined,
                proportion: currentYearSolidarity ? currentYearSolidarity.get('DF-2-4')/currentYearSolidarity.solidarityExpenditures : 1,
                text: `Le Département veille à protéger les enfants et les jeunes majeurs quand leur sécurité, leur santé et leur éducation sont menacées. Ce sont les professionnels de l’Aide sociale à l’enfance (ASE) qui assurent un suivi au plus près des familles. Si le danger rend impossible le maintien dans sa famille, l’enfant est pris en charge et est confié à des professionnels (familles d’accueil, maison d’enfants à caractère social, centre départemental de l’enfance et de la famille, foyer de l’enfance).
https://www.gironde.fr/enfance-et-famille/protection-de-lenfance.`,
                highlights: [
                    {
                        strong: "177 M€",
                        span: "pour les Maisons d’Enfants à Caractère Sociale"
                    },
                    {
                        strong: "4269",
                        span: "enfants accueillis en établissement et familles d’accueil en 2017"
                    },
                    {
                        strong: "796",
                        span: " assistants familiaux pour l'accueil familial"
                    }
                ],
                moreUrl: '#!/finance-details/DF-2-4'
            })
        )
    );

}

const YearSolidarityRecord = Record({
    totalExpenditures: 0,
    solidarityExpenditures: 0,
    'DF-1-1': 0,
    'DF-1-2': 0,
    'DF-1-3': 0,
    'DF-1-4': 0,
    'DF-1-other': 0,
    'DF-2-1': 0,
    'DF-2-2': 0,
    'DF-2-3': 0,
    'DF-2-4': 0,
    'DF-2-5': 0
})

export default connect(
    state => {
        const { docBudgByYear, corrections, currentYear, screenWidth } = state;

        const solidarityByYear = docBudgByYear.map( ((instruction) => {
            const agg = m52ToAggregated(instruction, corrections);

            const hierAgg = hierarchicalAggregated(agg);

            const hierAggByPrestationList = flattenTree(hierAgg);

            const expenditures = hierAggByPrestationList.find(e => e.id === EXPENDITURES).total;
            let solidarityExpenditures = hierAggByPrestationList.find(e => e.id === 'DF-1').total;
            const ysrData = {};
            ['DF-1-1', 'DF-1-2', 'DF-1-3', 'DF-1-4', 'DF-2-1', 'DF-2-2', 'DF-2-3', 'DF-2-4', 'DF-2-5'].forEach(id => {
                ysrData[id] = hierAggByPrestationList.find(e => e.id === id).total;
            });

            let df1other = solidarityExpenditures - (ysrData['DF-1-1'] + ysrData['DF-1-2'] + ysrData['DF-1-3'] + ysrData['DF-1-4']);

            return new YearSolidarityRecord(Object.assign(
                {
                    totalExpenditures: expenditures,
                    solidarityExpenditures,
                    'DF-1-other': df1other
                },
                ysrData
            ))
        }))

        return {
            currentYear,
            currentYearSolidarity: solidarityByYear.get(currentYear),
            solidarityByYear,
            screenWidth,
            urls
        };
    },
    () => ({})
)(FocusSol);
<|endoftext|>


<commit_before>describe('$meteorSession service', function () {
  var $meteorSession,
      $rootScope,
      $scope;

  beforeEach(angular.mock.module('angular-meteor'));

  beforeEach(angular.mock.inject(function(_$meteorSession_, _$rootScope_) {
    $meteorSession = _$meteorSession_;
    $rootScope = _$rootScope_;
    $scope = $rootScope.$new();
  }));

  it('should update the scope variable when session variable changes', function () {
    Session.set('myVar', 3);
    $meteorSession('myVar').bind($scope, 'myVar');

    Session.set('myVar', 4);
    Tracker.flush(); // get the computations to run

    expect($scope.myVar).toEqual(4);
  });

  it('should update the session variable when the scope variable changes', function() {
    $scope.myVar = 3;
    $meteorSession('myVar').bind($scope, 'myVar');

    $scope.myVar = 4;
    $rootScope.$apply();

    expect(Session.get('myVar')).toEqual(4);
  });
});
<commit_msg>Add test for $meteorSession service to support scope variable nested property<commit_after>describe('$meteorSession service', function () {
  var $meteorSession,
      $rootScope,
      $scope;

  beforeEach(angular.mock.module('angular-meteor'));

  beforeEach(angular.mock.inject(function(_$meteorSession_, _$rootScope_) {
    $meteorSession = _$meteorSession_;
    $rootScope = _$rootScope_;
    $scope = $rootScope.$new();
  }));

  it('should update the scope variable when session variable changes', function () {
    Session.set('myVar', 3);
    $meteorSession('myVar').bind($scope, 'myVar');

    Session.set('myVar', 4);
    Tracker.flush(); // get the computations to run

    expect($scope.myVar).toEqual(4);
  });

  it('should update the session variable when the scope variable changes', function() {
    $scope.myVar = 3;
    $meteorSession('myVar').bind($scope, 'myVar');

    $scope.myVar = 4;
    $rootScope.$apply();

    expect(Session.get('myVar')).toEqual(4);
  });

  it('should update the scope variable nested property when session variable changes', function () {
    Session.set('myVar', 3);
    $scope.a ={
      b:{
        myVar: 3
      }
    };

    $meteorSession('myVar').bind($scope, 'a.b.myVar');

    Session.set('myVar', 4);
    Tracker.flush(); // get the computations to run

    expect($scope.a.b.myVar).toEqual(4);
  });

  it('should update the session variable when the scope variable nested property changes', function() {
    $scope.a ={
      b:{
        myVar: 3
      }
    };
    $meteorSession('myVar').bind($scope, 'a.b.myVar');

    $scope.a.b.myVar = 4;
    $rootScope.$apply();

    expect(Session.get('myVar')).toEqual(4);
  });
});
<|endoftext|>


<commit_before>import React from 'react'
import { Segment, Menu, Input } from 'semantic-ui-react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as Actions from './../../actions'
import { withRouter } from 'react-router-dom'

import Annotator from '../../components/Annotator'

import './dashboard.css'

class Dashboard extends React.Component {
  constructor () {
    super()
    this.state = {
      activeItem: 'elections'
    }
  }

  handleItemClick = (e, { name }) => this.setState({ activeItem: name })

  render () {
    const { activeItem } = this.state
    return (

        <Menu attached='top' tabular className='dashboard-menu'>
          <Menu.Item name='elections' active={activeItem === 'elections'} onClick={this.handleItemClick} />
          <Menu.Item name='candidates' active={activeItem === 'candidates'} onClick={this.handleItemClick} />
          <Menu.Item name='media' active={activeItem === 'media'} onClick={this.handleItemClick} />
          <Menu.Item name='articles' active={activeItem === 'articles'} onClick={this.handleItemClick} />
          <Menu.Item name='users' active={activeItem === 'users'} onClick={this.handleItemClick} />
          <Menu.Item name='articles-labeling' active={activeItem === 'articles-labeling'} onClick={this.handleItemClick} />
          <Menu.Menu position='right'>
            <Menu.Item>
              <Input transparent icon={{ name: 'search', link: true }} placeholder='Search...' />
            </Menu.Item>
          </Menu.Menu>
        </Menu>
        <Segment attached='bottom'>
          <Annotator />
        </Segment>

    )
  }
}

const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated
})

const mapDispatchToProps = dispatch => ({
  actions: bindActionCreators(Actions, dispatch)
})

const DashboardContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(Dashboard)

export default withRouter(DashboardContainer)
<commit_msg>Add some menus<commit_after>import React from 'react'
import { Segment, Menu, Input } from 'semantic-ui-react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as Actions from './../../actions'
import { withRouter } from 'react-router-dom'

import Annotator from '../../components/Annotator'

import './dashboard.css'

class Dashboard extends React.Component {
  constructor () {
    super()
    this.state = {
      activeItem: 'articles-labeling'
    }
  }

  handleItemClick = (e, { name }) => this.setState({ activeItem: name })

  render () {
    const { activeItem } = this.state
    return (

        <Menu attached='top' tabular className='dashboard-menu'>
          <Menu.Item name='articles-labeling' active={activeItem === 'articles-labeling'} onClick={this.handleItemClick} />
          <Menu.Item name='elections' active={activeItem === 'elections'} onClick={this.handleItemClick} />
          <Menu.Item name='candidates' active={activeItem === 'candidates'} onClick={this.handleItemClick} />
          <Menu.Item name='media' active={activeItem === 'media'} onClick={this.handleItemClick} />
          <Menu.Item name='articles' active={activeItem === 'articles'} onClick={this.handleItemClick} />
          <Menu.Item name='users' active={activeItem === 'users'} onClick={this.handleItemClick} />
          <Menu.Item name='groups' active={activeItem === 'groups'} onClick={this.handleItemClick} />
          <Menu.Item name='permissions' active={activeItem === 'permissions'} onClick={this.handleItemClick} />
          <Menu.Menu position='right'>
            <Menu.Item>
              <Input transparent icon={{ name: 'search', link: true }} placeholder='Search...' />
            </Menu.Item>
          </Menu.Menu>
        </Menu>
        <Segment attached='bottom'>
          <Annotator />
        </Segment>

    )
  }
}

const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated
})

const mapDispatchToProps = dispatch => ({
  actions: bindActionCreators(Actions, dispatch)
})

const DashboardContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(Dashboard)

export default withRouter(DashboardContainer)
<|endoftext|>


<commit_before>import { Component, PropTypes } from 'react';
import os from 'os';
import semver from 'semver';

export const semverValidator = (props, propName, componentName) => {
  if (props[propName]) {
    return semver.validRange(props[propName]) ? null : new Error(`${propName} in ${componentName} is not a valid semver string`);
  }
  return null;
};

export default class PlatformSpecific extends Component {
  static propTypes = {
    children: PropTypes.object,
    platform: PropTypes.string.isRequired,
    versionRange: semverValidator,
  };

  render() {
    if (process.platform === this.props.platform) {
      if (!this.props.versionRange) return this.props.children;

      if (semver.validRange(this.props.versionRange) && semver.satisfies(os.release(), this.props.versionRange)) {
        return this.props.children;
      }
    }
    return null;
  }
}
<commit_msg>Fix version tests on linux<commit_after>import { Component, PropTypes } from 'react';
import os from 'os';
import semver from 'semver';

const parsedOSVersion = semver.parse(os.release());
const osVersion = `${parsedOSVersion.major}.${parsedOSVersion.minor}.${parsedOSVersion.patch}`;

export const semverValidator = (props, propName, componentName) => {
  if (props[propName]) {
    return semver.validRange(props[propName]) ? null : new Error(`${propName} in ${componentName} is not a valid semver string`);
  }
  return null;
};

export default class PlatformSpecific extends Component {
  static propTypes = {
    children: PropTypes.object,
    platform: PropTypes.string.isRequired,
    versionRange: semverValidator,
  };

  render() {
    if (process.platform === this.props.platform) {
      if (!this.props.versionRange) return this.props.children;

      if (semver.validRange(this.props.versionRange) && semver.satisfies(osVersion, this.props.versionRange)) {
        return this.props.children;
      }
    }
    return null;
  }
}
<|endoftext|>


<commit_before>//Contains all the icky test setup stuff,
//so that updater-test.js can focus on the business logic

const chai = require('chai')
const assert = chai.assert

const testFixture = require("./test-fixture")
var updater = null

/*
  getUpdater() returns an updater with mocked child_process.
 When the updater tries to run a script (via child_process.execFileSync,
 the mock intercepts it and instead just sets updater.lastExecutedFile
 Also sets updater.lastExecutedFileOptions
 See https://nodejs.org/api/child_process.html#child_process_child_process_execfilesync_file_args_options
 */
function getUpdater() {
  const mockery = require('mockery')
  mockery.registerMock('child_process')

  const childProcessMock = {
    execSync: function(command, options) {
      console.log("execSync", command)
      if (command.startsWith("chmod")) {
        //Ignore chmod
        return
      }

      updater.lastExecutedCommand = command
      updater.lastExecutedCommandOptions = options

      if (testFixture.shouldNextUpdateScriptSucceed) {
        return "update successful!"
      } else {
        throw new Error("update failed!")
      }
    },

    execFileSync: function(path, args, options) {
      console.log("execFileSync", path)
      updater.lastExecutedCommand = path
      updater.lastExecutedCommandOptions = options

      if (testFixture.shouldNextUpdateScriptSucceed) {
        return "update successful!"
      } else {
        throw new Error("update failed!")
      }
    },

    spawn: function(path, args, options) {
      console.log("spawn", path)
      updater.lastExecutedCommand = path
      updater.lastExecutedCommandOptions = options
    }
  }

  mockery.registerMock('child_process', childProcessMock)

  mockery.enable({
    warnOnReplace: false,
    warnOnUnregistered: false
  });

  const Updater = require("../src/updater.js")
  updater = new Updater("/updatertest", 'http://fakeupdater.com',
    {
      updateScriptTimeoutSeconds: 1,
      sshTunnelCommand: "echo 'No sshTunnelCommand configured'",
      onUpdating: function(updating) {
        if (updating) {
          updater.onUpdatingWasCalledWithTrue = true
        } else {
          updater.onUpdatingWasCalledWithFalse = true
        }
      }
    }
  )
  updater.lastExecutedFile = null
  updater.lastExecutedFileOptions = null

  mockery.disable()

  return updater
}

exports.getUpdater = getUpdater<commit_msg>Fixed a broken test (false negative)<commit_after>//Contains all the icky test setup stuff,
//so that updater-test.js can focus on the business logic

const chai = require('chai')
const assert = chai.assert

const testFixture = require("./test-fixture")
var updater = null

/*
  getUpdater() returns an updater with mocked child_process.
 When the updater tries to run a script (via child_process.execFileSync,
 the mock intercepts it and instead just sets updater.lastExecutedFile
 Also sets updater.lastExecutedFileOptions
 See https://nodejs.org/api/child_process.html#child_process_child_process_execfilesync_file_args_options
 */
function getUpdater() {
  const mockery = require('mockery')
  mockery.registerMock('child_process')

  const childProcessMock = {
    execSync: function(command, options) {
      console.log("execSync", command)
      if (command.startsWith("chmod")) {
        //Ignore chmod
        return
      }

      updater.lastExecutedCommand = command
      updater.lastExecutedCommandOptions = options

      if (testFixture.shouldNextUpdateScriptSucceed) {
        return "update successful!"
      } else {
        throw new Error("update failed!")
      }
    },

    execFileSync: function(path, args, options) {
      console.log("execFileSync", path)
      updater.lastExecutedCommand = path
      updater.lastExecutedCommandOptions = options

      if (testFixture.shouldNextUpdateScriptSucceed) {
        return "update successful!"
      } else {
        throw new Error("update failed!")
      }
    },

    exec: function(path, args, options) {
      console.log("exec", path)
      updater.lastExecutedCommand = path
      updater.lastExecutedCommandOptions = options
    }
  }

  mockery.registerMock('child_process', childProcessMock)

  mockery.enable({
    warnOnReplace: false,
    warnOnUnregistered: false
  });

  const Updater = require("../src/updater.js")
  updater = new Updater("/updatertest", 'http://fakeupdater.com',
    {
      updateScriptTimeoutSeconds: 1,
      sshTunnelCommand: "echo 'No sshTunnelCommand configured'",
      onUpdating: function(updating) {
        if (updating) {
          updater.onUpdatingWasCalledWithTrue = true
        } else {
          updater.onUpdatingWasCalledWithFalse = true
        }
      }
    }
  )
  updater.lastExecutedFile = null
  updater.lastExecutedFileOptions = null

  mockery.disable()

  return updater
}

exports.getUpdater = getUpdater<|endoftext|>


<commit_before>angular.module('n52.core.phenomena')
        .controller('SwcPhenomenaButtonController', ['$scope', 'statusService',
            function ($scope, statusService) {
                $scope.status = statusService.status;
                $scope.togglePhenomena = function () {
                    statusService.status.showPhenomena = !statusService.status.showPhenomena;
                };
            }]);<commit_msg>add phenomenon attribute to phenomenon button to show selected phenomenon<commit_after>angular.module('n52.core.phenomena')
        .controller('SwcPhenomenaButtonController', ['$scope', 'statusService', 'PhenomenonListFactory',
            function ($scope, statusService, PhenomenonListFactory) {
                $scope.status = statusService.status;

                $scope.selectedPhenomenon = PhenomenonListFactory.phenomena;

                $scope.togglePhenomena = function () {
                    statusService.status.showPhenomena = !statusService.status.showPhenomena;
                };
            }]);<|endoftext|>


<commit_before>import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import Ember from 'ember';

Ember.Test.registerAsyncHelper('sleep', function(app, duration) {
  return new Ember.RSVP.Promise(function(resolve) {
    setTimeout(resolve, duration);
  });
});

moduleForComponent('hold-button', 'Integration | Component | hold button', {
  integration: true
});

test('it renders', function(assert) {
  assert.expect(4);

  this.render(hbs`{{hold-button delay=0 action='finished'}}`);
  let $component = this.$('.ember-hold-button');
  assert.equal($component.length, 1);
  assert.ok(!$component.hasClass('is-holding'), "is-holding class not added");
  assert.ok(!$component.hasClass('is-complete'), "is-complete class not added");

  // Template block usage:
  this.render(hbs`
    {{#hold-button}}
      template block text
    {{/hold-button}}
  `);

  assert.equal(this.$().text().trim(), 'template block text');
});

test('it calls the action', function(assert) {
  assert.expect(4);
  this.render(hbs`{{hold-button delay=0 action='finished'}}`);
  let $component = this.$('.ember-hold-button');

  let finished = false;
  this.on('finished', function() {
    finished = true;
  });

  $component.mousedown();
  Ember.run.later(() => {
    assert.ok($component.hasClass('is-holding'), "is-holding class added");
    $component.mouseup();

    Ember.run.later(() => {
      assert.ok(!$component.hasClass('is-holding'), "is-holding class removed");
      assert.ok($component.hasClass('is-complete'), "is-complete class added");
      assert.ok(finished, "finished action called", "finish called");
    });
  });
});

test('type reflects CSS class', function(assert) {
  assert.expect(1);
  this.render(hbs`{{hold-button delay=0 action='finished' type='banana'}}`);
  let $component = this.$('.ember-hold-button');
  assert.ok($component.hasClass('banana'), "type class added");
});
<commit_msg>Test animation duration set correctly<commit_after>import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import Ember from 'ember';

Ember.Test.registerAsyncHelper('sleep', function(app, duration) {
  return new Ember.RSVP.Promise(function(resolve) {
    setTimeout(resolve, duration);
  });
});

moduleForComponent('hold-button', 'Integration | Component | hold button', {
  integration: true
});

test('it renders', function(assert) {
  assert.expect(4);

  this.render(hbs`{{hold-button delay=0 action='finished'}}`);
  let $component = this.$('.ember-hold-button');
  assert.equal($component.length, 1);
  assert.ok(!$component.hasClass('is-holding'), "is-holding class not added");
  assert.ok(!$component.hasClass('is-complete'), "is-complete class not added");

  // Template block usage:
  this.render(hbs`
    {{#hold-button}}
      template block text
    {{/hold-button}}
  `);

  assert.equal(this.$().text().trim(), 'template block text');
});

test('animation time set on inline style', function(assert) {
  this.render(hbs`{{hold-button delay=600 action='finished'}}`);
  let $span = this.$('.ember-hold-button > span');

  let duration = $span.css('transition-duration');
  assert.equal(duration.indexOf("0.6"), 0);
});

test('it calls the action', function(assert) {
  assert.expect(4);
  this.render(hbs`{{hold-button delay=0 action='finished'}}`);
  let $component = this.$('.ember-hold-button');

  let finished = false;
  this.on('finished', function() {
    finished = true;
  });

  $component.mousedown();
  Ember.run.later(() => {
    assert.ok($component.hasClass('is-holding'), "is-holding class added");
    $component.mouseup();

    Ember.run.later(() => {
      assert.ok(!$component.hasClass('is-holding'), "is-holding class removed");
      assert.ok($component.hasClass('is-complete'), "is-complete class added");
      assert.ok(finished, "finished action called", "finish called");
    });
  });
});

test('type reflects CSS class', function(assert) {
  assert.expect(1);
  this.render(hbs`{{hold-button delay=0 action='finished' type='banana'}}`);
  let $component = this.$('.ember-hold-button');
  assert.ok($component.hasClass('banana'), "type class added");
});
<|endoftext|>


<commit_before>const {Base} = require('@ash-framework/classes')
const createRoutes = require('@ash-framework/router')
const Log = require('@ash-framework/log')
const loadMiddleware = require('@ash-framework/middleware')
const express = require('express')
const path = require('path')
const fs = require('fs')

const _app = new WeakMap()

module.exports = class Application extends Base {
  static start () {
    const config = require(path.join(process.cwd(), 'config/environment.js'))(process.env.NODE_ENV)
    const MiddlewareRouter = require(path.join(process.cwd(), 'app/middleware.js'))
    const Router = require(path.join(process.cwd(), 'app/router.js'))
    const log = new Log()

    log.trace('Ash server creating express app instance')
    const app = express()
    _app.set(this, app)

    log.trace('Ash server loading middleware')
    const middlewareDir = path.join(process.cwd(), 'app/middleware')
    loadMiddleware(MiddlewareRouter.definition, app, middlewareDir)

    log.trace('Ash server loading routes')
    const options = {routesDir: path.join(process.cwd(), 'app/routes')}
    app.use(createRoutes(Router.definition, options))

    const initializerDir = path.join(process.cwd(), 'app/initializers')
    if (fs.existsSync(initializerDir)) {
      const initializers = fs.readdirSync(initializerDir)
      if (initializers.length > 0) {
        log.trace('Ash server loading initializers')
        initializers.forEach(initializerName => {
          const Initializer = require(initializerDir + '/' + initializerName)
          const initializer = new Initializer()
          initializer.init(app)
        })
      }
    }

    app.listen(config.port, function () {
      log.trace(`Ash server started on port ${config.port}`)
    })
  }
}
<commit_msg>Adds 404 handler and all other error handler<commit_after>const {Base} = require('@ash-framework/classes')
const createRoutes = require('@ash-framework/router')
const Log = require('@ash-framework/log')
const loadMiddleware = require('@ash-framework/middleware')
const express = require('express')
const path = require('path')
const fs = require('fs')

const _app = new WeakMap()

module.exports = class Application extends Base {
  static start () {
    const config = require(path.join(process.cwd(), 'config/environment.js'))(process.env.NODE_ENV)
    const MiddlewareRouter = require(path.join(process.cwd(), 'app/middleware.js'))
    const Router = require(path.join(process.cwd(), 'app/router.js'))
    const log = new Log()

    log.trace('Ash server creating express app instance')
    const app = express()
    _app.set(this, app)

    log.trace('Ash server loading middleware')
    const middlewareDir = path.join(process.cwd(), 'app/middleware')
    loadMiddleware(MiddlewareRouter.definition, app, middlewareDir)

    log.trace('Ash server loading routes')
    const options = {routesDir: path.join(process.cwd(), 'app/routes')}
    app.use(createRoutes(Router.definition, options))

    const initializerDir = path.join(process.cwd(), 'app/initializers')
    if (fs.existsSync(initializerDir)) {
      const initializers = fs.readdirSync(initializerDir)
      if (initializers.length > 0) {
        log.trace('Ash server loading initializers')
        initializers.forEach(initializerName => {
          const Initializer = require(initializerDir + '/' + initializerName)
          const initializer = new Initializer()
          initializer.init(app)
        })
      }
    }

    log.trace('Ash server registering 404 handler')
    app.use(function (req, res, next) {
      log.warn(`${req.method} ${req.originalUrl} 404 Not found`)
      res.status(404)
      if (req.accepts().indexOf('application/json') !== -1) {
        res.send({status: 404, error: 'Not found'})
      } else {
        res.send('Not found')
      }
    })

    log.trace('Ash server registering error handler')
    app.use(function (err, req, res, next) {
      log.error(err.stack)
      const status = err.status || 500
      res.status(status)
      if (req.accepts().indexOf('application/json') !== -1) {
        res.send({status, error: err.message})
      } else {
        res.send(err.message)
      }
    })

    app.listen(config.port, function () {
      log.trace(`Ash server started on port ${config.port}`)
    })
  }
}
<|endoftext|>


<commit_before>/**
 * @typedef {object} Phaser.Types.Renderer.WebGL.WebGLTextureCompression
 * @since 3.55.0
 *
 * @property {object|undefined} ASTC - Indicates if ASTC compression is supported (mostly iOS).
 * @property {object|undefined} ATC - Indicates if ATC compression is supported.
 * @property {object|undefined} BPTC - Indicates if BPTC compression is supported.
 * @property {object|undefined} ETC - Indicates if ETC compression is supported (mostly Android).
 * @property {object|undefined} ETC1 - Indicates if ETC1 compression is supported (mostly Android).
 * @property {object|undefined} IMG - Indicates the browser supports true color images.
 * @property {object|undefined} PVRTC - Indicates if PVRTC compression is supported (mostly iOS).
 * @property {object|undefined} RGTC - Indicates if RGTC compression is supported (mostly iOS).
 * @property {object|undefined} S3TC - Indicates if S3TC compression is supported on current device (mostly Windows).
 * @property {object|undefined} S3TCRGB - Indicates if S3TCRGB compression is supported on current device (mostly Windows).
 */
<commit_msg>Update WebGLTextureCompression.js<commit_after>/**
 * @typedef {object} Phaser.Types.Renderer.WebGL.WebGLTextureCompression
 * @since 3.55.0
 *
 * @property {object|undefined} ASTC - Indicates if ASTC compression is supported (mostly iOS).
 * @property {object|undefined} ATC - Indicates if ATC compression is supported.
 * @property {object|undefined} BPTC - Indicates if BPTC compression is supported.
 * @property {object|undefined} ETC - Indicates if ETC compression is supported (mostly Android).
 * @property {object|undefined} ETC1 - Indicates if ETC1 compression is supported (mostly Android).
 * @property {object|undefined} IMG - Indicates the browser supports true color images (all browsers).
 * @property {object|undefined} PVRTC - Indicates if PVRTC compression is supported (mostly iOS).
 * @property {object|undefined} RGTC - Indicates if RGTC compression is supported (mostly iOS).
 * @property {object|undefined} S3TC - Indicates if S3TC compression is supported on current device (mostly Windows).
 * @property {object|undefined} S3TCRGB - Indicates if S3TCRGB compression is supported on current device (mostly Windows).
 */
<|endoftext|>


<commit_before>describe('daisy', function(){

	it('should not be undefined', function(){
		expect(daisy).not.toBe(undefined);
	});

	it('should be a function', function(){
		expect(typeof daisy).toBe('function');
	});

	describe('initialization', function(){

		it('should take a stringified positive integer', function(){
			var result = daisy('1');
			expect(result).not.toBe(undefined);
			expect(result.currentVal).toBe('1');
		});

		it('should take a stringified negative integer', function(){
			var result = daisy('-1');
			expect(result).not.toBe(undefined);
			expect(result.currentVal).toBe('-1');
		});

		it('should take a negative integer and convert to string', function(){
			var result = daisy(-1);
			expect(result.currentVal).toBe('-1');
		});

		it('should take a positive integer and convert to string', function(){
			var result = daisy(4);
			expect(result.currentVal).toBe('4');
		});

		it('should take a negative double and convert to string', function(){
			var result = daisy(-12.34);
			expect(result.currentVal).toBe('-12.34');
		});

		it('should take a positive double and convert to string', function(){
			var result = daisy(3.14);
			expect(result.currentVal).toBe('3.14');
		});

		it('should take an array of numbers', function(){
			var result = daisy([1, 2, 3, 4, 5]);
			expect(result.currentSet.length).toBe(5);
		});

		it('should return an object with an equals() function', function(){
			var result = daisy();
			expect(result.equals).not.toBe(undefined);
			expect(typeof result.equals).toBe('function');
		});

	});

	describe('equals', function(){

		it('should convert a positive integer to a dollar/cent value', function(){
			var actual = daisy(3).equals();
			expect(actual).toBe('3.00');
		});

		it('should convert a postive decimal to a dollar/cent value', function(){
			var actual = daisy(12.12).equals();
			expect(actual).toBe('12.12');
		});

		it('should convert a negative decimal to a dollar/cent value', function(){
			var actual = daisy(-453.32).equals();
			expect(actual).toBe('-453.32');
		});

		it('should convert a negative integer to a dollar/cent value', function(){
			var actual = daisy(-19).equals();
			expect(actual).toBe('-19.00');
		});

		it('should round positive overflows to the nearest cent', function(){
			var actual = daisy(4.1234).equals();
			expect(actual).toBe('4.12');
		});

		it('should round negative overflows to the nearest cent', function(){
			var actual = daisy('-12.22934').equals();
			expect(actual).toBe('-12.23');
		});

	});

	describe('plus', function(){

		it('should add two positive integers', function(){
			var actual = daisy(1).plus(1).equals();
			expect(actual).toBe('2.00');
		});

		it('should add three positive integers', function(){
			var actual = daisy(12).plus(14).plus(2).equals();
			expect(actual).toBe('28.00');
		});

	});

	describe('minus', function(){

		it('should subtract positive integers and give positive result', function(){
			var actual = daisy('8').minus(6).equals();
			expect(actual).toBe('2.00');
		});

		it('should substract three positive numbers and give positive result', function(){
			var actual = daisy('14').minus(8).minus(1).equals();
			expect(actual).toBe('5.00');
		});

		it('should subtract three positive numbers and give a negative result', function(){
			var actual = daisy('12').minus('12').minus(3.12).equals();
			expect(actual).toBe('-3.12');
		});

		it('should yield a zero just fine', function(){
			var actual = daisy('45560').minus(45560).equals();
			expect(actual).toBe('0.00');
		});

	});

	describe('times', function(){

		it('should multiply two positive numbers', function(){
			var actual = daisy('12').times('2').equals();
			expect(actual).toBe('24.00');
		});

		it('should multiply a pos and neg number and yield a negative result', function(){
			var actual = daisy('-12').times('3').equals();
			expect(actual).toBe('-36.00');
		});

		it('should multiply in a chain', function(){
			var actual = daisy('2').plus(4).times('4').equals();
			expect(actual).toBe('24.00');
		});

		it('should multiply by zero', function(){
			var actual = daisy('3').times('0').equals();
			expect(actual).toBe('0.00');
		});

	});

	describe('dividedBy', function(){

		it('should divide two positve numbers', function(){
			var actual = daisy('24').dividedBy(4).equals();
			expect(actual).toBe('6.00');
		});

		it('should divide two negative numbers', function(){
			var actual = daisy('-12.34544').times(1.234).dividedBy('-3.44').equals();
			expect(actual).toBe('4.43');
		});

	});

	describe('factorial', function(){

	});

	describe('NumberSet', function(){

		describe('sum', function(){

			it('should add an array of positive integers', function(){
				var actual = daisy([1, 2, 3]).sum().equals();
				expect(actual).toBe('6.00');
			});

			it('should sum an array of negative numbers and round', function(){
				var actual = daisy([
					-14.2,
					2.001,
					'-12.1'
				]).sum().equals();
				expect(actual).toBe('-24.30');
			});

		});

		describe('average', function(){

			it('should average an array of positive numbers and round', function(){
				var actual = daisy([
					'1.2',
					'4.45',
					'234.3',
					'25'
				]).average().equals();
				expect(actual).toBe('66.24');
			});

		});

		describe('max', function(){

			it('should take the max of a mixed set', function(){
				var actual = daisy([1, 2, 3, 4, -3, -1]).max().equals();
				expect(actual).toBe('4.00');
			});

			it('should take a max of invalid set with supressInvalidNumbers', function(){
				var actual = daisy([1, -10, 'baaaaaah'], { supressInvalidNumbers: true }).max().equals();
				expect(actual).toBe('1.00');
			});

		});

		describe('max', function(){

			it('should take the min of a mixed set', function(){
				var actual = daisy([1, 2, 3, 4, -3, -1]).min().equals();
				expect(actual).toBe('-3.00');
			});

			it('should take a min of invalid set with supressInvalidNumbers', function(){
				var actual = daisy([1, -10, 'baaaaaah'], { supressInvalidNumbers: true }).min().equals();
				expect(actual).toBe('-10.00');
			});

		});

	});

	describe('exceptions', function(){

		var passIfThrows = function(func, expectedMessage){
			var errored = false,
				actualMessage;
			try {
				func();
			} catch(e){
				errored = true;
				actualMessage = e.message;
			}
			expect(errored).toBe(true);
			expect(actualMessage).toBe(expectedMessage);
		};

		var failIfThrows = function(func){
			var errored = false;
			try { func(); } catch(e){ errored = true; }
			expect(errored).toBe(false);
		};

		it('should throw an error during plus with a bad value', function(){
			passIfThrows(function(){
				daisy('DJ KHALED').plus(2);
			}, '\'DJ KHALED\' is not a valid number');
		});

		it('should throw an error during minus with bad value', function(){
			passIfThrows(function(){
				daisy('3').minus('baby you smart');
			}, '\'baby you smart\' is not a valid number');
		});

		it('should throw an error during equals with a bad value', function(){
			passIfThrows(function(){
				daisy('say mai naaaaaame').equals();
			}, '\'say mai naaaaaame\' is not a valid number');
		});

		it('should not throw an error during init with bad value', function(){
			failIfThrows(function(){
				var result = daisy('we the best');
			});
		});

		it('should throw an error if summing an empty set', function(){
			passIfThrows(function(){
				daisy([]).sum();
			}, 'cannot operate on empty set');
		});

		it('should throw an error if averaging an empty set', function(){
			passIfThrows(function(){
				daisy([]).average();
			}, 'cannot operate on empty set');
		});

		it('should not throw an error during init with empty set', function(){
			failIfThrows(function(){
				daisy([]);
			});
		});

		it('should throw an error if summing a set with a bad value', function(){
			passIfThrows(function(){
				daisy(['2', '-2', 'ITUNES NEEDS MORE SERVERS']).sum().equals();
			}, '\'ITUNES NEEDS MORE SERVERS\' is not a valid number');
		});

		it('should throw an error if averaging a set with a bad value', function(){
			passIfThrows(function(){
				daisy([-2, -1, 0, 2, 'fishsticks', 3]).average();
			}, '\'fishsticks\' is not a valid number');
		});

		it('should throw an error if calling reduce on an empty or null array', function(){
			passIfThrows(function(){
				[].reduce(function(){});
			}, 'Reduce of empty array with no initial value');
			passIfThrows(function(){
				[1, 2].reduce('notAFunction');
			}, 'notAFunction is not a function');
		});

		it('should throw a div by zero exception', function(){
			passIfThrows(function(){
				daisy('4').dividedBy(0);
			}, 'divided \'4\' by zero');
		});

		it('should thrown exception when getting max or min of empty set', function(){
			passIfThrows(function(){
				daisy([]).max().equals();
			}, 'cannot operate on empty set');
			passIfThrows(function(){
				daisy([]).min();
			}, 'cannot operate on empty set');
		});

	});

	describe('options', function(){

		it('should return value if dollar sign if printDollarSign', function(){
			var actual = daisy('3', {
				printDollarSign: true,
			}).plus(3).equals();
			expect(actual).toBe('$6.00');

			actual = daisy('3.40', {
				printDollarSign: true,
			}).dividedBy(-2.3).equals();
			expect(actual).toBe('$-1.48');
		});

		it('should assume divide by zero is zero if supressDivideByZero', function(){
			var actual = daisy('3', {
				printDollarSign: true,
				supressDivideByZero: true
			}).dividedBy(0).equals();
			expect(actual).toBe('$0.00');
		});

		it('should assume zero for invalid numbers if supressInvalidNumbers', function(){
			var actual = daisy('3', { supressInvalidNumbers: true }).plus('meh').equals();
			expect(actual).toBe('3.00');
		});

		it('should sum an invalid set if supressInvalidNumbers', function(){
			var actual = daisy([
				'not',
				'actual',
				'numbers'
			], {
				supressInvalidNumbers: true
			}).sum().equals();
			expect(actual).toBe('0.00');
		});

		it('should take the average of an invalid set if supressInvalidNumbers', function(){
			var actual = daisy([
				'1',
				'2',
				'boop'
			], {
				supressInvalidNumbers: true
			}).average().equals();
			expect(actual).toBe('1.00');
		});

	});

});<commit_msg>Small test change for coverage.<commit_after>describe('daisy', function(){

	it('should not be undefined', function(){
		expect(daisy).not.toBe(undefined);
	});

	it('should be a function', function(){
		expect(typeof daisy).toBe('function');
	});

	describe('initialization', function(){

		it('should take a stringified positive integer', function(){
			var result = daisy('1');
			expect(result).not.toBe(undefined);
			expect(result.currentVal).toBe('1');
		});

		it('should take a stringified negative integer', function(){
			var result = daisy('-1');
			expect(result).not.toBe(undefined);
			expect(result.currentVal).toBe('-1');
		});

		it('should take a negative integer and convert to string', function(){
			var result = daisy(-1);
			expect(result.currentVal).toBe('-1');
		});

		it('should take a positive integer and convert to string', function(){
			var result = daisy(4);
			expect(result.currentVal).toBe('4');
		});

		it('should take a negative double and convert to string', function(){
			var result = daisy(-12.34);
			expect(result.currentVal).toBe('-12.34');
		});

		it('should take a positive double and convert to string', function(){
			var result = daisy(3.14);
			expect(result.currentVal).toBe('3.14');
		});

		it('should take an array of numbers', function(){
			var result = daisy([1, 2, 3, 4, 5]);
			expect(result.currentSet.length).toBe(5);
		});

		it('should return an object with an equals() function', function(){
			var result = daisy();
			expect(result.equals).not.toBe(undefined);
			expect(typeof result.equals).toBe('function');
		});

	});

	describe('equals', function(){

		it('should convert a positive integer to a dollar/cent value', function(){
			var actual = daisy(3).equals();
			expect(actual).toBe('3.00');
		});

		it('should convert a postive decimal to a dollar/cent value', function(){
			var actual = daisy(12.12).equals();
			expect(actual).toBe('12.12');
		});

		it('should convert a negative decimal to a dollar/cent value', function(){
			var actual = daisy(-453.32).equals();
			expect(actual).toBe('-453.32');
		});

		it('should convert a negative integer to a dollar/cent value', function(){
			var actual = daisy(-19).equals();
			expect(actual).toBe('-19.00');
		});

		it('should round positive overflows to the nearest cent', function(){
			var actual = daisy(4.1234).equals();
			expect(actual).toBe('4.12');
		});

		it('should round negative overflows to the nearest cent', function(){
			var actual = daisy('-12.22934').equals();
			expect(actual).toBe('-12.23');
		});

	});

	describe('plus', function(){

		it('should add two positive integers', function(){
			var actual = daisy(1).plus(1).equals();
			expect(actual).toBe('2.00');
		});

		it('should add three positive integers', function(){
			var actual = daisy(12).plus(14).plus(2).equals();
			expect(actual).toBe('28.00');
		});

	});

	describe('minus', function(){

		it('should subtract positive integers and give positive result', function(){
			var actual = daisy('8').minus(6).equals();
			expect(actual).toBe('2.00');
		});

		it('should substract three positive numbers and give positive result', function(){
			var actual = daisy('14').minus(8).minus(1).equals();
			expect(actual).toBe('5.00');
		});

		it('should subtract three positive numbers and give a negative result', function(){
			var actual = daisy('12').minus('12').minus(3.12).equals();
			expect(actual).toBe('-3.12');
		});

		it('should yield a zero just fine', function(){
			var actual = daisy('45560').minus(45560).equals();
			expect(actual).toBe('0.00');
		});

	});

	describe('times', function(){

		it('should multiply two positive numbers', function(){
			var actual = daisy('12').times('2').equals();
			expect(actual).toBe('24.00');
		});

		it('should multiply a pos and neg number and yield a negative result', function(){
			var actual = daisy('-12').times('3').equals();
			expect(actual).toBe('-36.00');
		});

		it('should multiply in a chain', function(){
			var actual = daisy('2').plus(4).times('4').equals();
			expect(actual).toBe('24.00');
		});

		it('should multiply by zero', function(){
			var actual = daisy('3').times('0').equals();
			expect(actual).toBe('0.00');
		});

	});

	describe('dividedBy', function(){

		it('should divide two positve numbers', function(){
			var actual = daisy('24').dividedBy(4).equals();
			expect(actual).toBe('6.00');
		});

		it('should divide two negative numbers', function(){
			var actual = daisy('-12.34544').times(1.234).dividedBy('-3.44').equals();
			expect(actual).toBe('4.43');
		});

	});

	describe('factorial', function(){

	});

	describe('NumberSet', function(){

		describe('sum', function(){

			it('should add an array of positive integers', function(){
				var actual = daisy([1, 2, 3]).sum().equals();
				expect(actual).toBe('6.00');
			});

			it('should sum an array of negative numbers and round', function(){
				var actual = daisy([
					-14.2,
					2.001,
					'-12.1'
				]).sum().equals();
				expect(actual).toBe('-24.30');
			});

		});

		describe('average', function(){

			it('should average an array of positive numbers and round', function(){
				var actual = daisy([
					'1.2',
					'4.45',
					'234.3',
					'25'
				]).average().equals();
				expect(actual).toBe('66.24');
			});

		});

		describe('max', function(){

			it('should take the max of a mixed set', function(){
				var actual = daisy([1, 2, 3, 4, -3, -1]).max().equals();
				expect(actual).toBe('4.00');
			});

			it('should take a max of invalid set with supressInvalidNumbers', function(){
				var actual = daisy([1, -10, 'baaaaaah', 10], { supressInvalidNumbers: true }).max().equals();
				expect(actual).toBe('10.00');
			});

		});

		describe('min', function(){

			it('should take the min of a mixed set', function(){
				var actual = daisy([1, 2, 3, 4, -3, -1]).min().equals();
				expect(actual).toBe('-3.00');
			});

			it('should take a min of invalid set with supressInvalidNumbers', function(){
				var actual = daisy([1, -10, 'baaaaaah'], { supressInvalidNumbers: true }).min().equals();
				expect(actual).toBe('-10.00');
			});

		});

	});

	describe('exceptions', function(){

		var passIfThrows = function(func, expectedMessage){
			var errored = false,
				actualMessage;
			try {
				func();
			} catch(e){
				errored = true;
				actualMessage = e.message;
			}
			expect(errored).toBe(true);
			expect(actualMessage).toBe(expectedMessage);
		};

		var failIfThrows = function(func){
			var errored = false;
			try { func(); } catch(e){ errored = true; }
			expect(errored).toBe(false);
		};

		it('should throw an error during plus with a bad value', function(){
			passIfThrows(function(){
				daisy('DJ KHALED').plus(2);
			}, '\'DJ KHALED\' is not a valid number');
		});

		it('should throw an error during minus with bad value', function(){
			passIfThrows(function(){
				daisy('3').minus('baby you smart');
			}, '\'baby you smart\' is not a valid number');
		});

		it('should throw an error during equals with a bad value', function(){
			passIfThrows(function(){
				daisy('say mai naaaaaame').equals();
			}, '\'say mai naaaaaame\' is not a valid number');
		});

		it('should not throw an error during init with bad value', function(){
			failIfThrows(function(){
				var result = daisy('we the best');
			});
		});

		it('should throw an error if summing an empty set', function(){
			passIfThrows(function(){
				daisy([]).sum();
			}, 'cannot operate on empty set');
		});

		it('should throw an error if averaging an empty set', function(){
			passIfThrows(function(){
				daisy([]).average();
			}, 'cannot operate on empty set');
		});

		it('should not throw an error during init with empty set', function(){
			failIfThrows(function(){
				daisy([]);
			});
		});

		it('should throw an error if summing a set with a bad value', function(){
			passIfThrows(function(){
				daisy(['2', '-2', 'ITUNES NEEDS MORE SERVERS']).sum().equals();
			}, '\'ITUNES NEEDS MORE SERVERS\' is not a valid number');
		});

		it('should throw an error if averaging a set with a bad value', function(){
			passIfThrows(function(){
				daisy([-2, -1, 0, 2, 'fishsticks', 3]).average();
			}, '\'fishsticks\' is not a valid number');
		});

		it('should throw an error if calling reduce on an empty or null array', function(){
			passIfThrows(function(){
				[].reduce(function(){});
			}, 'Reduce of empty array with no initial value');
			passIfThrows(function(){
				[1, 2].reduce('notAFunction');
			}, 'notAFunction is not a function');
		});

		it('should throw a div by zero exception', function(){
			passIfThrows(function(){
				daisy('4').dividedBy(0);
			}, 'divided \'4\' by zero');
		});

		it('should thrown exception when getting max or min of empty set', function(){
			passIfThrows(function(){
				daisy([]).max().equals();
			}, 'cannot operate on empty set');
			passIfThrows(function(){
				daisy([]).min();
			}, 'cannot operate on empty set');
		});

	});

	describe('options', function(){

		it('should return value if dollar sign if printDollarSign', function(){
			var actual = daisy('3', {
				printDollarSign: true,
			}).plus(3).equals();
			expect(actual).toBe('$6.00');

			actual = daisy('3.40', {
				printDollarSign: true,
			}).dividedBy(-2.3).equals();
			expect(actual).toBe('$-1.48');
		});

		it('should assume divide by zero is zero if supressDivideByZero', function(){
			var actual = daisy('3', {
				printDollarSign: true,
				supressDivideByZero: true
			}).dividedBy(0).equals();
			expect(actual).toBe('$0.00');
		});

		it('should assume zero for invalid numbers if supressInvalidNumbers', function(){
			var actual = daisy('3', { supressInvalidNumbers: true }).plus('meh').equals();
			expect(actual).toBe('3.00');
		});

		it('should sum an invalid set if supressInvalidNumbers', function(){
			var actual = daisy([
				'not',
				'actual',
				'numbers'
			], {
				supressInvalidNumbers: true
			}).sum().equals();
			expect(actual).toBe('0.00');
		});

		it('should take the average of an invalid set if supressInvalidNumbers', function(){
			var actual = daisy([
				'1',
				'2',
				'boop'
			], {
				supressInvalidNumbers: true
			}).average().equals();
			expect(actual).toBe('1.00');
		});

	});

});<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { storiesOf } from '@storybook/react';

import { Box, Grommet, CheckBox } from 'grommet';
import { grommet } from 'grommet/themes';

class IndeterminateCheckBox extends Component {
  state = {
    checked: [],
    checkboxes: ['fruits', 'vegetables', 'olive oil'],
  };

  onCheckAll = event => {
    const { checkboxes } = this.state;
    if (event.target.checked) {
      this.setState({ checked: checkboxes });
    } else {
      this.setState({ checked: [] });
    }
  };

  onCheck = (event, value) => {
    const { checked } = this.state;
    if (event.target.checked) {
      checked.push(value);
      this.setState({ checked });
    } else {
      this.setState({ checked: checked.filter(item => item !== value) });
    }
  };

  render() {
    const { checked, checkboxes } = this.state;

    return (
      <Grommet theme={grommet}>
        <Box align="center" pad="large">
          <Box direction="row" gap="medium">
            <CheckBox
              checked={checked.length === 3}
              indeterminate={checked.length > 0 && checked.length < 3}
              label="All"
              onChange={this.onCheckAll}
            />
            {checkboxes.map(item => (
              <CheckBox
                key={item}
                checked={checked.indexOf(item) !== -1}
                label={item}
                onChange={e => this.onCheck(e, item)}
              />
            ))}
          </Box>
        </Box>
      </Grommet>
    );
  }
}

storiesOf('CheckBox', module).add('Interminate', () => (
  <IndeterminateCheckBox />
));
<commit_msg>convert class based checbox-indeterminate.js to hooks #3394 Signed-off-by: … (#3410)<commit_after>import React, { useState } from 'react';
import { storiesOf } from '@storybook/react';

import { Box, Grommet, CheckBox } from 'grommet';
import { grommet } from 'grommet/themes';

const IndeterminateCheckBox = () => {
  const [checked, setChecked] = useState([]);
  const checkboxes = ['fruits', 'vegetables', 'olive oil'];

  const onCheckAll = event => {
    if (event.target.checked) {
      setChecked(checkboxes);
    } else {
      setChecked([]);
    }
  };

  const onCheck = (event, value) => {
    if (event.target.checked) {
      setChecked([...checked, value]);
    } else {
      setChecked(checked.filter(item => item !== value));
    }
  };

  return (
    <Grommet theme={grommet}>
      <Box align="center" pad="large">
        <Box direction="row" gap="medium">
          <CheckBox
            checked={checked.length === 3}
            indeterminate={checked.length > 0 && checked.length < 3}
            label="All"
            onChange={onCheckAll}
          />
          {checkboxes.map(item => (
            <CheckBox
              key={item}
              checked={checked.includes(item)}
              label={item}
              onChange={e => onCheck(e, item)}
            />
          ))}
        </Box>
      </Box>
    </Grommet>
  );
};

storiesOf('CheckBox', module).add('Interminate', () => (
  <IndeterminateCheckBox />
));
<|endoftext|>


<commit_before>import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('modal-title', 'Integration | Component | modal title', {
  integration: true
});

test('it renders', function(assert) {
  assert.expect(2);

  // Set any properties with this.set('myProperty', 'value');
  // Handle any actions with this.on('myAction', function(val) { ... });

  this.render(hbs`{{modal-title}}`);

  assert.equal(this.$().text().trim(), '');

  // Template block usage:
  this.render(hbs`
    {{#modal-title}}
      template block text
    {{/modal-title}}
  `);

  assert.equal(this.$().text().trim(), 'template block text');
});
<commit_msg>Reparando tests del componente modal-title<commit_after>import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('modal-title', 'Integration | Component | modal title', {
  integration: true
});

test('it renders', function(assert) {
  assert.expect(1);

  this.render(hbs`{{modal-title}}`);

  this.render(hbs`
    {{#modal-title}}
      template block text
    {{/modal-title}}
  `);

  assert.equal(this.$().text().trim(), 'Cerrar');
});
<|endoftext|>


<commit_before>// Copyright (c) 2012 Titanium I.T. LLC. All rights reserved. See LICENSE.txt for details.
/*global describe, it, expect, dump, jQuery, $, wwp, afterEach beforeEach Raphael*/

(function() {
  "use strict";

  describe("Drawing area", function() {

    var drawingArea;
    var paper;

    //beforeEach(function(){
    //});

    afterEach(function() {
      drawingArea.remove();
    });

    it("should have the same dimensions as its enclosing div", function() {
      drawingArea = $("
hi
");
      $(document.body).append(drawingArea);
      paper = wwp.initializeDrawingArea(drawingArea[0]);
      expect(paper.width).to.equal(400);
      expect(paper.height).to.equal(200);
    });

    it("should draw a line", function(){
      wwp.drawLine(20, 30, 30, 300);
      var elements = drawingElements(paper);
      expect(elements.length).to.equal(1);
      expect(pathFor(elements[0])).to.equal("M20,30L30,300");
    });

    function clickMouse(pageX, pageY) {
      var eventData = new jQuery.Event();
      eventData.pageX = pageX;
      eventData.pageY = pageY;
      eventData.type = 'click';
      drawingArea.trigger(eventData);
    }

    function relativePosition(drawingArea, pageX, pageY) {
      var topLeftOfDrawingArea = drawingArea.offset();
      var x = pageX - topLeftOfDrawingArea.left;
      var y = pageY - topLeftOfDrawingArea.top;
      return {x: x, y: y};
    }

    it("draws line segments in response to clicks", function() {
      drawingArea = $("
hi
");
      $(document.body).append(drawingArea);
      paper = wwp.initializeDrawingArea(drawingArea[0]);

      clickMouse(20, 30);
      clickMouse(50, 60);

      var start = relativePosition(drawingArea, 20, 30);
      var end = relativePosition(drawingArea, 50, 60);

      var elements = drawingElements(paper);
      expect(elements.length).to.equal(1);
      expect(pathFor(elements[0])).to.equal("M" + start.x + ',' + start.y + "L" + end.x + ',' + end.y);
    });

    //it("considers border when calculating mouse target", function(){
      //drawingArea = $("
hi
");
      //$(document.body).append(drawingArea);
      //paper = wwp.initializeDrawingArea(drawingArea[0]);

      //var eventData = new jQuery.Event();
      //eventData.pageX = 20;
      //eventData.pageY = 30;
      //eventData.type = 'click';

      //drawingArea.trigger(eventData);

      //var topLeftOfDrawingArea = drawingArea.offset();
      //var borderWidth = 13;
      //var expectedX = 20 - topLeftOfDrawingArea.left - borderWidth;
      //var expectedY = 30 - topLeftOfDrawingArea.top - borderWidth;

      //var elements = drawingElements(paper);
      //expect(elements.length).to.equal(1);
      //expect(pathFor(elements[0])).to.equal("M0,0L" + expectedX + ',' + expectedY);
    //});

    function drawingElements(paper) {
      var result = [];
      paper.forEach(function (element) {
        result.push(element);
      });
      return result;
    }

    function pathFor(element) {
      var box = element.getBBox();
      return 'M' + box.x + ',' + box.y + 'L' + box.x2 + ',' + box.y2;

      //if(Raphael.vml) return vmlPathfor(element);
      //else if(Raphael.svg) return svgPathfor(element);
      //else throw new Error("Unknown Raphael type");
    }

    //function svgPathfor(element){
      //var path = element.node.attributes.d.value;
      //if(path.indexOf(",") !== -1){
        //return path;
      //}else{
        //var ie9PathRegex = /M (\d+) (\d+) L (\d+) (\d+)/;
        //var ie9 = path.match(ie9PathRegex);
        //return "M" + ie9[1] + "," + ie9[2] + "L" + ie9[3] + "," + ie9[4];
      //}
    //}

    //function vmlPathfor(element){
       //var VLM_MAGIC_NUMBER = 21600;
        //var path = element.node.path.value;
        //var ie8PathRegex = /m(\d+),(\d+) l(\d+),(\d+) e/;
        //var ie8 = path.match(ie8PathRegex);
        //var startX = ie8[1] / VLM_MAGIC_NUMBER;
        //var startY = ie8[2] / VLM_MAGIC_NUMBER;
        //var endX = ie8[3] / VLM_MAGIC_NUMBER;
        //var endY = ie8[4] / VLM_MAGIC_NUMBER;
        //return 'M' + startX + ',' + startY + 'L' + endX + ',' + endY;
    //}

  });
}());
<commit_msg>End of episode 56<commit_after>// Copyright (c) 2012 Titanium I.T. LLC. All rights reserved. See LICENSE.txt for details.
/*global describe, it, expect, dump, jQuery, $, wwp, afterEach beforeEach Raphael*/

(function() {
  "use strict";

  describe("Drawing area", function() {

    var drawingArea;
    var paper;

    //beforeEach(function(){
    //});

    afterEach(function() {
      drawingArea.remove();
    });

    it("should have the same dimensions as its enclosing div", function() {
      drawingArea = $("
hi
");
      $(document.body).append(drawingArea);
      paper = wwp.initializeDrawingArea(drawingArea[0]);
      expect(paper.width).to.equal(400);
      expect(paper.height).to.equal(200);
    });

    it("should draw a line", function(){
      wwp.drawLine(20, 30, 30, 300);
      var elements = drawingElements(paper);
      expect(elements.length).to.equal(1);
      expect(pathFor(elements[0])).to.equal("M20,30L30,300");
    });

    function clickMouse(pageX, pageY) {
      var eventData = new jQuery.Event();
      eventData.pageX = pageX;
      eventData.pageY = pageY;
      eventData.type = 'click';
      drawingArea.trigger(eventData);
    }

    function relativePosition(drawingArea, pageX, pageY) {
      var topLeftOfDrawingArea = drawingArea.offset();
      var x = pageX - topLeftOfDrawingArea.left;
      var y = pageY - topLeftOfDrawingArea.top;
      return {x: x, y: y};
    }

    it("draws line segments in response to clicks", function() {
      drawingArea = $("
hi
");
      $(document.body).append(drawingArea);
      paper = wwp.initializeDrawingArea(drawingArea[0]);

      clickMouse(20, 30);
      clickMouse(50, 60);
      clickMouse(40, 20);

      var start = relativePosition(drawingArea, 20, 30);
      var end = relativePosition(drawingArea, 50, 60);

      var elements = drawingElements(paper);
      expect(elements.length).to.equal(2);
      expect(pathFor(elements[0])).to.equal("M" + start.x + ',' + start.y + "L" + end.x + ',' + end.y);
    });

    //it("considers border when calculating mouse target", function(){
      //drawingArea = $("
hi
");
      //$(document.body).append(drawingArea);
      //paper = wwp.initializeDrawingArea(drawingArea[0]);

      //var eventData = new jQuery.Event();
      //eventData.pageX = 20;
      //eventData.pageY = 30;
      //eventData.type = 'click';

      //drawingArea.trigger(eventData);

      //var topLeftOfDrawingArea = drawingArea.offset();
      //var borderWidth = 13;
      //var expectedX = 20 - topLeftOfDrawingArea.left - borderWidth;
      //var expectedY = 30 - topLeftOfDrawingArea.top - borderWidth;

      //var elements = drawingElements(paper);
      //expect(elements.length).to.equal(1);
      //expect(pathFor(elements[0])).to.equal("M0,0L" + expectedX + ',' + expectedY);
    //});

    function drawingElements(paper) {
      var result = [];
      paper.forEach(function (element) {
        result.push(element);
      });
      return result;
    }

    function pathFor(element) {
      var box = element.getBBox();
      return 'M' + box.x + ',' + box.y + 'L' + box.x2 + ',' + box.y2;

      //if(Raphael.vml) return vmlPathfor(element);
      //else if(Raphael.svg) return svgPathfor(element);
      //else throw new Error("Unknown Raphael type");
    }

    //function svgPathfor(element){
      //var path = element.node.attributes.d.value;
      //if(path.indexOf(",") !== -1){
        //return path;
      //}else{
        //var ie9PathRegex = /M (\d+) (\d+) L (\d+) (\d+)/;
        //var ie9 = path.match(ie9PathRegex);
        //return "M" + ie9[1] + "," + ie9[2] + "L" + ie9[3] + "," + ie9[4];
      //}
    //}

    //function vmlPathfor(element){
       //var VLM_MAGIC_NUMBER = 21600;
        //var path = element.node.path.value;
        //var ie8PathRegex = /m(\d+),(\d+) l(\d+),(\d+) e/;
        //var ie8 = path.match(ie8PathRegex);
        //var startX = ie8[1] / VLM_MAGIC_NUMBER;
        //var startY = ie8[2] / VLM_MAGIC_NUMBER;
        //var endX = ie8[3] / VLM_MAGIC_NUMBER;
        //var endY = ie8[4] / VLM_MAGIC_NUMBER;
        //return 'M' + startX + ',' + startY + 'L' + endX + ',' + endY;
    //}

  });
}());
<|endoftext|>


<commit_before><commit_msg>Fix for content-length<commit_after><|endoftext|>