...

Source file src/github.com/gobuffalo/flect/flect_test.go

Documentation: github.com/gobuffalo/flect

     1  package flect
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  type tt struct {
    12  	act string
    13  	exp string
    14  }
    15  
    16  func Test_LoadInflections(t *testing.T) {
    17  	r := require.New(t)
    18  	m := map[string]string{
    19  		"baby": "bebe",
    20  		"xyz":  "zyx",
    21  	}
    22  
    23  	b, err := json.Marshal(m)
    24  	r.NoError(err)
    25  
    26  	r.NoError(LoadInflections(bytes.NewReader(b)))
    27  
    28  	for k, v := range m {
    29  		r.Equal(v, Pluralize(k))
    30  		r.Equal(v, Pluralize(v))
    31  		r.Equal(k, Singularize(k))
    32  		r.Equal(k, Singularize(v))
    33  	}
    34  }
    35  
    36  func Test_LoadInflectionsWrongSingular(t *testing.T) {
    37  	r := require.New(t)
    38  	m := map[string]string{
    39  		"a file": "files",
    40  	}
    41  
    42  	b, err := json.Marshal(m)
    43  	r.NoError(err)
    44  
    45  	r.Error(LoadInflections(bytes.NewReader(b)))
    46  }
    47  
    48  func Test_LoadInflectionsWrongPlural(t *testing.T) {
    49  	r := require.New(t)
    50  	m := map[string]string{
    51  		"beatle": "the beatles",
    52  	}
    53  
    54  	b, err := json.Marshal(m)
    55  	r.NoError(err)
    56  
    57  	r.Error(LoadInflections(bytes.NewReader(b)))
    58  }
    59  
    60  func Test_LoadAcronyms(t *testing.T) {
    61  	r := require.New(t)
    62  	m := []string{
    63  		"ACC",
    64  		"TLC",
    65  		"LSA",
    66  	}
    67  
    68  	b, err := json.Marshal(m)
    69  	r.NoError(err)
    70  
    71  	r.NoError(LoadAcronyms(bytes.NewReader(b)))
    72  
    73  	for _, acronym := range m {
    74  		r.True(baseAcronyms[acronym])
    75  	}
    76  }
    77  
    78  type dict struct {
    79  	singular          string
    80  	plural            string
    81  	doSingularizeTest bool
    82  	doPluralizeTest   bool
    83  }
    84  
    85  var singlePluralAssertions = []dict{
    86  	{"", "", true, true},
    87  	{"Car", "Cars", true, true},
    88  	{"Boy", "Boys", true, true},
    89  	{"GoodBoy", "GoodBoys", true, true},
    90  	{"Axis", "Axes", true, true},
    91  	{"Child", "Children", true, true},
    92  	{"GoodChild", "GoodChildren", true, true},
    93  	{"node_child", "node_children", true, true},
    94  	{"SmartPerson", "SmartPeople", true, true},
    95  	{"great_person", "great_people", true, true},
    96  	{"salesperson", "salespeople", true, true},
    97  	{"custom_field", "custom_fields", true, true},
    98  	{"funky jeans", "funky jeans", true, true},
    99  	{"payment_information", "payment_information", true, true},
   100  	{"sportsEquipment", "sportsEquipment", true, true},
   101  	{"status_code", "status_codes", true, true},
   102  	{"user_custom_field", "user_custom_fields", true, true},
   103  	{"SuperbOx", "SuperbOxen", true, true},
   104  	{"WildOx", "WildOxen", true, true},
   105  	{"wild_ox", "wild_oxen", true, true},
   106  	{"box", "boxes", true, true},
   107  	{"fox", "foxes", true, true},
   108  	{"comment", "comments", true, true},
   109  	{"edge", "edges", true, true},
   110  	{"equipment", "equipment", true, true},
   111  	{"experience", "experiences", true, true},
   112  	{"fleet", "fleets", true, true},
   113  	{"foobar", "foobars", true, true},
   114  	{"mouse", "mice", true, true},
   115  	{"newsletter", "newsletters", true, true},
   116  	{"stack", "stacks", true, true},
   117  	{"user", "users", true, true},
   118  	{"woman", "women", true, true},
   119  	{"human", "humans", true, true},
   120  	{"spokesman", "spokesmen", true, true},
   121  
   122  	// Words that end in -f or -fe change -f or -fe to -ves
   123  	// https://en.wiktionary.org/wiki/Category:English_irregular_plurals_ending_in_"-ves"
   124  	{"calf", "calves", true, true},
   125  	{"dwarf", "dwarves", true, false}, // dwarfs looks popular than dwarves
   126  	{"dwarf", "dwarfs", true, true},
   127  	{"elf", "elves", true, true},
   128  	{"half", "halves", true, true},
   129  	{"knife", "knives", true, true},
   130  	{"leaf", "leaves", true, true},
   131  	{"life", "lives", true, true},
   132  	{"loaf", "loaves", true, true},
   133  	{"safe", "saves", true, true},
   134  	{"scarf", "scarves", true, true},
   135  	{"self", "selves", true, true},
   136  	{"sheaf", "sheaves", true, true},
   137  	{"shelf", "shelves", true, true},
   138  	{"thief", "thieves", true, true},
   139  	{"wharf", "wharves", true, true},
   140  	{"wife", "wives", true, true},
   141  	{"wolf", "wolves", true, true},
   142  	{"beef", "beef", true, true},
   143  	{"belief", "beliefs", true, true},
   144  	{"chef", "chefs", true, true},
   145  	{"chief", "chiefs", true, true},
   146  	{"hoof", "hoofs", true, true},
   147  	{"kerchief", "kerchiefs", true, true},
   148  	{"roof", "roofs", true, true},
   149  	{"archive", "archives", true, true},
   150  	{"perspective", "perspectives", true, true},
   151  
   152  	// Words that end in -y preceded by a consonant change -y to -ies
   153  	{"day", "days", true, true},
   154  	{"hobby", "hobbies", true, true},
   155  	{"agency", "agencies", true, true},
   156  	{"body", "bodies", true, true},
   157  	{"abbey", "abbeys", true, true},
   158  	{"jiffy", "jiffies", true, true},
   159  	{"geology", "geologies", true, true},
   160  	{"geography", "geographies", true, true},
   161  	{"cookie", "cookies", true, true},
   162  	{"sky", "skies", true, true},
   163  	{"supply", "supplies", true, true},
   164  	{"academy", "academies", true, true},
   165  	{"ebony", "ebonies", true, true},
   166  	{"boy", "boys", true, true},
   167  	{"copy", "copies", true, true},
   168  	{"category", "categories", true, true},
   169  	{"embassy", "embassies", true, true},
   170  	{"entity", "entities", true, true},
   171  	{"guy", "guys", true, true},
   172  	{"obsequy", "obsequies", true, true},
   173  	{"navy", "navies", true, true},
   174  	{"proxy", "proxies", true, true},
   175  	{"crazy", "crazies", true, true},
   176  
   177  	// Words from French that end in -u add an x
   178  	{"aboideau", "aboideaux", true, true},
   179  	{"beau", "beaux", true, true},
   180  	{"château", "châteaux", true, true},
   181  	{"chateau", "chateaux", true, true},
   182  	{"fabliau", "fabliaux", true, true},
   183  	{"tableau", "tableaux", true, true},
   184  	{"bureau", "bureaus", true, true},
   185  	{"adieu", "adieux", true, true},
   186  
   187  	// Words from Greek that end in -on change -on to -a
   188  	{"tetrahedron", "tetrahedra", true, true},
   189  
   190  	// Words from Latin that end in -um change -um to -a
   191  	{"stadium", "stadiums", true, true},
   192  	{"stadium", "stadia", true, false},
   193  	{"aquarium", "aquaria", true, true},
   194  	{"auditorium", "auditoria", true, true},
   195  	{"bacterium", "bacteria", true, true},
   196  	{"pretorium", "pretoriums", true, true},
   197  	{"symposium", "symposia", true, true},
   198  	{"symposium", "symposiums", true, false},
   199  	{"amoebaeum", "amoebaea", true, true},
   200  	{"coliseum", "coliseums", true, true},
   201  	{"museum", "museums", true, true},
   202  	{"agenda", "agendas", true, true},
   203  	{"curriculum", "curriculums", true, true},
   204  	{"collum", "colla", true, true},
   205  	{"datum", "data", true, true},
   206  	{"erratum", "errata", true, true},
   207  	{"maximum", "maxima", true, true},
   208  	{"platinum", "platinums", true, true},
   209  	{"serum", "sera", true, true},
   210  	{"spectrum", "spectra", true, true},
   211  
   212  	// Words from Latin that end in -us change -us to -i or -era
   213  	{"opera", "operas", true, true},
   214  
   215  	// Words from Latin that end in -a change -a to -ae
   216  	{"alumna", "alumnae", true, true},
   217  	{"larva", "larvae", true, true},
   218  	{"minutia", "minutiae", true, true},
   219  	{"nebula", "nebulae", true, true},
   220  	{"vertebra", "vertebrae", true, true},
   221  	{"vita", "vitae", true, true},
   222  	{"antenna", "antennas", true, true},
   223  	{"formula", "formulas", true, true},
   224  	{"tuna", "tuna", true, true},
   225  	{"quota", "quotas", true, true},
   226  	{"vedalia", "vedalias", true, true},
   227  	{"media", "media", true, true}, // instead of mediae, popular case
   228  	{"multimedia", "multimedia", true, true},
   229  
   230  	// Words that end in -ch, -o, -s, -sh, -x, -z
   231  	{"lunch", "lunches", true, true},
   232  	{"search", "searches", true, true},
   233  	{"switch", "switches", true, true},
   234  	{"headache", "headaches", true, true}, // ch vs. che
   235  	{"marsh", "marshes", true, true},
   236  	{"wish", "wishes", true, true},
   237  
   238  	{"bus", "buses", true, true}, // end with u + s, but no -us rule
   239  	{"campus", "campuses", true, true},
   240  	{"caucus", "caucuses", true, true},
   241  	{"circus", "circuses", true, true},
   242  	{"plus", "pluses", true, true},
   243  	{"prometheus", "prometheuses", true, true},
   244  	{"status", "statuses", true, true},
   245  	{"virus", "viruses", true, true},
   246  	{"use", "uses", true, true}, // -use
   247  	{"fuse", "fuses", true, true},
   248  	{"house", "houses", true, true},
   249  	{"spouse", "spouses", true, true},
   250  
   251  	{"quiz", "quizzes", true, true},
   252  	{"buzz", "buzzes", true, true},
   253  	{"blitz", "blitzes", true, true},
   254  	{"quartz", "quartzes", true, true},
   255  	{"topaz", "topazes", true, true},
   256  	{"waltz", "waltzes", true, true},
   257  	{"prize", "prizes", true, true},
   258  
   259  	{"access", "accesses", true, true},
   260  	{"process", "processes", true, true},
   261  	{"address", "addresses", true, true},
   262  	{"case", "cases", true, true},
   263  	{"database", "databases", true, true},
   264  	{"glimpse", "glimpses", true, true},
   265  	{"horse", "horses", true, true},
   266  	{"lapse", "lapses", true, true},
   267  	{"collapse", "collapses", true, true},
   268  	{"truss", "trusses", true, true},
   269  
   270  	{"portfolio", "portfolios", true, true}, // -o -os
   271  	{"piano", "pianos", true, true},         // -ano -anos
   272  	{"hello", "hellos", true, true},         // -lo -los
   273  	{"buffalo", "buffaloes", true, true},    // -lo -loes
   274  	{"photo", "photos", true, true},         // -to -tos
   275  	{"potato", "potatoes", true, true},      // exception of -to -tos
   276  	{"tomato", "tomatoes", true, true},
   277  	{"graffiti", "graffiti", true, true},
   278  	{"foo", "foos", true, true},
   279  	{"zoo", "zoos", true, true},
   280  
   281  	// Words from Latin that end in -ex change -ex to -ices
   282  	// Words from Latin that end in -ix change -ix to -ices
   283  	{"appendix", "appendices", true, true}, // -dix
   284  	{"codex", "codices", true, true},       // -dex
   285  	{"index", "indices", true, true},
   286  	{"bodice", "bodices", true, true},    // -dice
   287  	{"helix", "helices", true, true},     // -lix
   288  	{"complex", "complexes", true, true}, // -lex
   289  	{"duplex", "duplexes", true, true},
   290  	{"accomplice", "accomplices", true, true}, // -lice
   291  	{"slice", "slices", true, true},
   292  	{"matrix", "matrices", true, true},  // -trix
   293  	{"justice", "justices", true, true}, // -tice
   294  	{"lattice", "lattices", true, true},
   295  	{"notice", "notices", true, true},
   296  	{"apex", "apices", true, true},    // -pex
   297  	{"spice", "spices", true, true},   // -pice
   298  	{"device", "devices", true, true}, // -vice
   299  	{"service", "services", true, true},
   300  	{"fix", "fixes", true, true},        // -ix
   301  	{"sex", "sexes", true, true},        // -ex
   302  	{"invoice", "invoices", true, true}, // gobuffalo/flect#61
   303  	{"voice", "voices", true, true},
   304  	{"choice", "choices", true, true},
   305  
   306  	// Words from Latin that end in -is change -is to -es
   307  	{"axis", "axes", true, true},
   308  	{"tax", "taxes", true, true}, // not taxis
   309  	{"eclipse", "eclipses", true, true},
   310  	{"ellipse", "ellipses", true, true},
   311  	{"ellipsis", "ellipses", false, true}, // pluralize only
   312  	{"oasis", "oases", true, true},
   313  	{"thesis", "theses", true, true}, // word thesis
   314  	{"hypothesis", "hypotheses", true, true},
   315  	{"parenthesis", "parentheses", true, true},
   316  	{"analysis", "analyses", true, true}, // suffix lysis
   317  	{"antithesis", "antitheses", true, true},
   318  	{"diagnosis", "diagnoses", true, true}, // suffix gnosis
   319  	{"prognosis", "prognoses", true, true},
   320  	{"synopsis", "synopses", true, true}, // suffix opsis
   321  	{"synapse", "synapses", true, true},
   322  	{"waste", "wastes", true, true},
   323  	{"psi", "psis", true, true},
   324  	{"pepsi", "pepsis", true, true},
   325  
   326  	// Acronyms
   327  	{"widget_uuid", "widget_uuids", true, true},
   328  	{"WidgetUUID", "WidgetUUIDs", true, true},
   329  	{"widgetUUID", "widgetUUIDs", true, true},
   330  	{"widgetUuid", "widgetUuids", true, true},
   331  	{"widget_UUID", "widget_UUIDs", true, true},
   332  
   333  	{"ID", "IDs", true, true},
   334  	{"IDS", "IDSes", true, true},
   335  	// id to ids (ID), ids to idses (IDS) is not supported
   336  	{"api", "apis", true, true},
   337  	{"API", "APIs", true, true},
   338  	{"html", "htmls", true, true},
   339  	{"HTML", "HTMLs", true, true},
   340  	{"FYI", "FYIs", true, true},
   341  	{"LAN", "LANs", true, true},
   342  	{"ssh", "sshs", true, true}, // sh
   343  	{"SSH", "SSHs", true, true},
   344  	{"eia", "eias", true, true}, // ia
   345  	{"EIA", "EIAs", true, true},
   346  	{"DNS", "DNSes", true, true},
   347  }
   348  
   349  func init() {
   350  	for _, wd := range dictionary {
   351  		if wd.uncountable && wd.plural == "" {
   352  			wd.plural = wd.singular
   353  		}
   354  
   355  		singlePluralAssertions = append(singlePluralAssertions, dict{
   356  			singular:          wd.singular,
   357  			plural:            wd.plural,
   358  			doSingularizeTest: !wd.unidirectional,
   359  		})
   360  
   361  		if wd.alternative != "" {
   362  			singlePluralAssertions = append(singlePluralAssertions, dict{
   363  				singular:        wd.singular,
   364  				plural:          wd.alternative,
   365  				doPluralizeTest: false,
   366  			})
   367  		}
   368  	}
   369  }
   370  

View as plain text